Merge JDK-8200758-branch
authorherrick
Tue, 26 Mar 2019 09:05:10 -0400
branchJDK-8200758-branch
changeset 57284 8786618d2a55
parent 57283 0b0be19f79e4 (current diff)
parent 54280 a33c42262338 (diff)
child 57285 c7f237482015
Merge
make/CompileJavaModules.gmk
src/hotspot/os_cpu/linux_x86/gc/z/zLargePages_linux_x86.cpp
src/hotspot/os_cpu/linux_x86/gc/z/zNUMA_linux_x86.cpp
src/hotspot/os_cpu/linux_x86/gc/z/zVirtualMemory_linux_x86.cpp
src/hotspot/share/gc/z/zForwardingTableEntry.hpp
src/hotspot/share/gc/z/zNMethodAllocator.cpp
src/hotspot/share/gc/z/zNMethodAllocator.hpp
src/hotspot/share/gc/z/zPageTableEntry.hpp
src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c
src/java.base/unix/native/libnio/ch/UnixAsynchronousServerSocketChannelImpl.c
src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-tibetan.cc
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.h
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-digest-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-impl-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode-private.hh
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-utf-private.hh
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationBailoutActionHelp.txt
src/jdk.sctp/unix/native/libsctp/SctpServerChannelImpl.c
test/hotspot/gtest/gc/z/test_zForwardingTable.cpp
test/hotspot/jtreg/runtime/RedefineObject/Agent.java
test/hotspot/jtreg/runtime/RedefineObject/TestRedefineObject.java
test/hotspot/jtreg/runtime/RedefineObject/WalkThroughInvoke.java
test/hotspot/jtreg/runtime/RedefineTests/ModifyAnonymous.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineAddLambdaExpression.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineAnnotations.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineDeleteJmethod.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineDoubleDelete.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineFinalizer.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceCall.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceMethods.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineLeak.java
test/hotspot/jtreg/runtime/RedefineTests/RedefinePreviousVersions.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethods.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java
test/hotspot/jtreg/runtime/RedefineTests/RedefineSubtractLambdaExpression.java
test/hotspot/jtreg/runtime/RedefineTests/TestMultipleClasses.java
test/hotspot/jtreg/runtime/RedefineTests/libRedefineDeleteJmethod.c
test/hotspot/jtreg/runtime/RedefineTests/libRedefineDoubleDelete.c
test/hotspot/jtreg/runtime/handshake/HandshakeWalkSuspendExitTest.java
test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.c
test/hotspot/jtreg/serviceability/jvmti/RetransformClassesZeroLength.java
test/hotspot/jtreg/serviceability/jvmti/TestLambdaFormRetransformation.java
test/hotspot/jtreg/serviceability/jvmti/TestRedefineWithUnresolvedClass.java
test/hotspot/jtreg/serviceability/jvmti/UnresolvedClassAgent.java
test/hotspot/jtreg/serviceability/jvmti/UnresolvedClassAgent.mf
test/jdk/java/awt/Choice/PopdownGeneratesMouseEvents/PopdownGeneratesMouseEvents.html
test/jdk/java/awt/Choice/PopupPosTest/PopupPosTest.html
test/jdk/java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.html
test/jdk/java/awt/Component/F10TopToplevel/F10TopToplevel.html
test/jdk/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html
test/jdk/java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.html
test/jdk/java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest.html
test/jdk/java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.html
test/jdk/java/awt/Focus/ChildWindowFocusTest/ChildWindowFocusTest.html
test/jdk/java/awt/Focus/DeiconifiedFrameLoosesFocus/DeiconifiedFrameLoosesFocus.html
test/jdk/java/awt/Focus/FocusSubRequestTest/FocusSubRequestTest.html
test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.html
test/jdk/java/awt/Focus/ModalDialogInitialFocusTest/ModalDialogInitialFocusTest.html
test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.html
test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.html
test/jdk/java/awt/Focus/ToFrontFocusTest/ToFrontFocus.html
test/jdk/java/awt/Focus/WindowInitialFocusTest/WindowInitialFocusTest.html
test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.html
test/jdk/java/awt/FontClass/CreateFont/bigfont.html
test/jdk/java/awt/Frame/DisposeStressTest/DisposeStressTest.html
test/jdk/java/awt/Frame/NonEDT_GUI_DeadlockTest/NonEDT_GUI_Deadlock.html
test/jdk/java/awt/GridBagLayout/GridBagLayoutIpadXYTest/GridBagLayoutIpadXYTest.html
test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.html
test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.html
test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.html
test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/MenuItemActivatedTest/MenuItemActivatedTest.html
test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.html
test/jdk/java/awt/List/FirstItemRemoveTest/FirstItemRemoveTest.html
test/jdk/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html
test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.html
test/jdk/java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.html
test/jdk/java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.html
test/jdk/java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.html
test/jdk/java/awt/Window/HandleWindowDestroyTest/HandleWindowDestroyTest.html
test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.html
test/jdk/java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.html
test/jdk/java/awt/dnd/DragInterceptorAppletTest/DragInterceptorAppletTest.html
test/jdk/java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.html
test/jdk/java/awt/dnd/ImageDecoratedDnDInOut/ImageDecoratedDnDInOut.html
test/jdk/java/awt/dnd/ImageDecoratedDnDNegative/ImageDecoratedDnDNegative.html
test/jdk/java/awt/dnd/InterJVMGetDropSuccessTest/InterJVMGetDropSuccessTest.html
test/jdk/java/awt/dnd/NoFormatsCrashTest/NoFormatsCrashTest.html
test/jdk/java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.html
test/jdk/java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.html
test/jdk/java/awt/event/ComponentEvent/MovedResizedTardyEventTest/MovedResizedTardyEventTest.html
test/jdk/java/awt/event/KeyEvent/KeyTyped/CtrlASCII.html
test/jdk/java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsoluteCoordsTest.html
test/jdk/java/awt/event/MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.html
test/jdk/java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.html
test/jdk/java/awt/event/MouseEvent/MouseWheelEventAbsoluteCoordsTest/MouseWheelEventAbsoluteCoordsTest.html
test/jdk/java/awt/event/MouseEvent/RobotLWTest/RobotLWTest.html
test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_2.html
test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_3.html
test/jdk/javax/imageio/AppletResourceTest.html
test/jdk/javax/swing/JFrame/4962534/bug4962534.html
test/jdk/javax/swing/JPopupMenu/4634626/bug4634626.html
test/jdk/javax/swing/MultiUIDefaults/4300666/bug4300666.html
test/jdk/javax/swing/text/StyledEditorKit/4506788/bug4506788.html
test/jdk/sanity/client/TEST.ROOT.template
test/jdk/sun/java2d/cmm/ColorConvertOp/ConstructorsNullTest/ConstructorsNullTest.html
test/jdk/vm/JniInvocationTest.java
test/jdk/vm/exeJniInvocationTest.c
test/jdk/vm/gc/ArraySize.java
test/jdk/vm/gc/InfiniteList.java
test/jdk/vm/jit/BadLogicCode.java
test/jdk/vm/jit/ExceptionInInit.java
test/jdk/vm/jit/JITClassInit.java
test/jdk/vm/runtime/ExplicitArithmeticCheck.java
test/jdk/vm/runtime/MonitorCacheMaybeExpand_DeadLock.java
test/jdk/vm/runtime/ReflectStackOverflow.java
test/jdk/vm/runtime/ShiftTest.java
test/jdk/vm/runtime/WideStrictInline.java
test/jdk/vm/verifier/TestStaticIF.java
test/jdk/vm/verifier/VerifyProtectedConstructor.java
test/jdk/vm/verifier/VerifyStackForExceptionHandlers.java
test/jdk/vm/verifier/defaultMethods/DefaultMethodRegressionTests.java
test/jdk/vm/verifier/defaultMethods/DefaultMethodRegressionTestsRun.java
test/langtools/jdk/javadoc/tool/doclint/ImplicitHeadersTest.java
test/langtools/tools/javac/doclint/ImplicitHeadersTest.java
--- a/.hgtags	Tue Mar 26 08:57:28 2019 -0400
+++ b/.hgtags	Tue Mar 26 09:05:10 2019 -0400
@@ -548,3 +548,6 @@
 b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12+33
 8e069f7b4fabfe05d9f500783e6d56cb0196d25c jdk-13+10
 21ea4076a275a0f498afa517e9ee1b94a9cf0255 jdk-13+11
+1d7aec80147a6d92b101a76aef92f3ddc88bedf4 jdk-13+12
+b67884871b5fff79c5ef3eb8ac74dd48d71ea9b1 jdk-12-ga
+83cace4142c8563b6a921787db02388e1bc48d01 jdk-13+13
--- a/doc/testing.html	Tue Mar 26 08:57:28 2019 -0400
+++ b/doc/testing.html	Tue Mar 26 09:05:10 2019 -0400
@@ -39,7 +39,7 @@
 <h2 id="using-make-test-the-run-test-framework">Using &quot;make test&quot; (the run-test framework)</h2>
 <p>This new way of running tests is developer-centric. It assumes that you have built a JDK locally and want to test it. Running common test targets is simple, and more complex ad-hoc combination of tests is possible. The user interface is forgiving, and clearly report errors it cannot resolve.</p>
 <p>The main target <code>test</code> uses the jdk-image as the tested product. There is also an alternate target <code>exploded-test</code> that uses the exploded image instead. Not all tests will run successfully on the exploded image, but using this target can greatly improve rebuild times for certain workflows.</p>
-<p>Previously, <code>make test</code> was used invoke an old system for running test, and <code>make run-test</code> was used for the new test framework. For backward compatibility with scripts and muscle memory, <code>run-test</code> (and variants like <code>exploded-run-test</code> or <code>run-test-tier1</code>) are kept as aliases. The old system can still be accessed for some time using <code>cd test &amp;&amp; make</code>.</p>
+<p>Previously, <code>make test</code> was used to invoke an old system for running tests, and <code>make run-test</code> was used for the new test framework. For backward compatibility with scripts and muscle memory, <code>run-test</code> (and variants like <code>exploded-run-test</code> or <code>run-test-tier1</code>) are kept as aliases.</p>
 <p>Some example command-lines:</p>
 <pre><code>$ make test-tier1
 $ make test-jdk_lang JTREG=&quot;JOBS=8&quot;
--- a/doc/testing.md	Tue Mar 26 08:57:28 2019 -0400
+++ b/doc/testing.md	Tue Mar 26 09:05:10 2019 -0400
@@ -12,11 +12,10 @@
 instead. Not all tests will run successfully on the exploded image, but using
 this target can greatly improve rebuild times for certain workflows.
 
-Previously, `make test` was used invoke an old system for running test, and
+Previously, `make test` was used to invoke an old system for running tests, and
 `make run-test` was used for the new test framework. For backward compatibility
 with scripts and muscle memory, `run-test` (and variants like
-`exploded-run-test` or `run-test-tier1`) are kept as aliases. The old system
-can still be accessed for some time using `cd test && make`.
+`exploded-run-test` or `run-test-tier1`) are kept as aliases.
 
 Some example command-lines:
 
--- a/make/CompileJavaModules.gmk	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/CompileJavaModules.gmk	Tue Mar 26 09:05:10 2019 -0400
@@ -38,7 +38,7 @@
 ################################################################################
 # Module specific build settings
 
-java.base_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*' -XDstringConcat=inline
+java.base_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference,-accessibility '-Xdoclint/package:java.*,javax.*' -XDstringConcat=inline
 java.base_COPY += .icu .dat .spp content-types.properties hijrah-config-islamic-umalqura.properties
 java.base_CLEAN += intrinsic.properties
 
@@ -79,7 +79,7 @@
 
 ################################################################################
 
-java.desktop_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference \
+java.desktop_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference,-accessibility \
     '-Xdoclint/package:java.*,javax.*' -Xlint:exports \
     --doclint-format html4
 java.desktop_COPY += .gif .png .wav .txt .xml .css .pf
@@ -220,15 +220,15 @@
 
 ################################################################################
 
-java.instrument_ADD_JAVAC_FLAGS += -Xdoclint:all/protected '-Xdoclint/package:java.*,javax.*'
+java.instrument_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-accessibility '-Xdoclint/package:java.*,javax.*'
 
 ################################################################################
 
-java.logging_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*'
+java.logging_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference,-accessibility '-Xdoclint/package:java.*,javax.*'
 
 ################################################################################
 
-java.management_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference '-Xdoclint/package:java.*,javax.*'
+java.management_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-reference,-accessibility '-Xdoclint/package:java.*,javax.*'
 
 ################################################################################
 
@@ -249,7 +249,7 @@
 
 ################################################################################
 
-java.sql.rowset_ADD_JAVAC_FLAGS += -Xdoclint:all/protected '-Xdoclint/package:java.*,javax.*'
+java.sql.rowset_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-accessibility '-Xdoclint/package:java.*,javax.*'
 java.sql.rowset_CLEAN_FILES += $(wildcard \
     $(TOPDIR)/src/java.sql.rowset/share/classes/com/sun/rowset/*.properties \
     $(TOPDIR)/src/java.sql.rowset/share/classes/javax/sql/rowset/*.properties)
@@ -263,14 +263,14 @@
 
 ################################################################################
 
-java.xml_ADD_JAVAC_FLAGS += -Xdoclint:all/protected \
+java.xml_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-accessibility \
     '-Xdoclint/package:$(call CommaList, javax.xml.catalog javax.xml.datatype \
     javax.xml.transform javax.xml.validation javax.xml.xpath)'
 java.xml_CLEAN += .properties
 
 ################################################################################
 
-java.naming_ADD_JAVAC_FLAGS += -Xdoclint:all/protected '-Xdoclint/package:java.*,javax.*' -Xlint:-exports
+java.naming_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-accessibility '-Xdoclint/package:java.*,javax.*' -Xlint:-exports
 java.naming_CLEAN += jndiprovider.properties
 
 ################################################################################
@@ -279,7 +279,7 @@
 
 ################################################################################
 
-java.smartcardio_ADD_JAVAC_FLAGS += -Xdoclint:all/protected '-Xdoclint/package:java.*,javax.*'
+java.smartcardio_ADD_JAVAC_FLAGS += -Xdoclint:all/protected,-accessibility '-Xdoclint/package:java.*,javax.*'
 
 ################################################################################
 
--- a/make/autoconf/lib-x11.m4	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/autoconf/lib-x11.m4	Tue Mar 26 09:05:10 2019 -0400
@@ -119,7 +119,7 @@
 
     if test "x$X11_HEADERS_OK" = xno; then
       HELP_MSG_MISSING_DEPENDENCY([x11])
-      AC_MSG_ERROR([Could not find all X11 headers (shape.h Xrender.h Xrander.h XTest.h Intrinsic.h). $HELP_MSG])
+      AC_MSG_ERROR([Could not find all X11 headers (shape.h Xrender.h Xrandr.h XTest.h Intrinsic.h). $HELP_MSG])
     fi
 
     # If XLinearGradient isn't available in Xrender.h, signal that it needs to be
--- a/make/autoconf/toolchain.m4	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/autoconf/toolchain.m4	Tue Mar 26 09:05:10 2019 -0400
@@ -643,14 +643,21 @@
     [ LINKER_VERSION_NUMBER=`$ECHO $LINKER_VERSION_STRING | \
         $SED -e 's/.* \([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*/\1/'` ]
   elif test  "x$TOOLCHAIN_TYPE" = xgcc; then
-    # gcc -Wl,-version output typically looks like
+    # gcc -Wl,-version output typically looks like:
     #   GNU ld (GNU Binutils for Ubuntu) 2.26.1
     #   Copyright (C) 2015 Free Software Foundation, Inc.
     #   This program is free software; [...]
-    LINKER_VERSION_STRING=`$LD -Wl,-version 2>&1 | $HEAD -n 1`
+    # If using gold it will look like:
+    #   GNU gold (GNU Binutils 2.30) 1.15
+    LINKER_VERSION_STRING=`$LD -Wl,--version 2> /dev/null | $HEAD -n 1`
     # Extract version number
-    [ LINKER_VERSION_NUMBER=`$ECHO $LINKER_VERSION_STRING | \
-        $SED -e 's/.* \([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*/\1/'` ]
+    if [ [[ "$LINKER_VERSION_STRING" == *gold* ]] ]; then
+      [ LINKER_VERSION_NUMBER=`$ECHO $LINKER_VERSION_STRING | \
+          $SED -e 's/.* \([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*) .*/\1/'` ]
+    else
+      [ LINKER_VERSION_NUMBER=`$ECHO $LINKER_VERSION_STRING | \
+          $SED -e 's/.* \([0-9][0-9]*\(\.[0-9][0-9]*\)*\).*/\1/'` ]
+    fi
   elif test  "x$TOOLCHAIN_TYPE" = xclang; then
     # clang -Wl,-v output typically looks like
     #   @(#)PROGRAM:ld  PROJECT:ld64-305
--- a/make/autoconf/toolchain_windows.m4	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/autoconf/toolchain_windows.m4	Tue Mar 26 09:05:10 2019 -0400
@@ -87,6 +87,7 @@
 VS_VS_PLATFORM_NAME_2017="v141"
 VS_SDK_PLATFORM_NAME_2017=
 VS_SUPPORTED_2017=true
+VS_TOOLSET_SUPPORTED_2017=true
 
 ################################################################################
 
@@ -177,6 +178,15 @@
 # build environment and assigns it to VS_ENV_CMD
 AC_DEFUN([TOOLCHAIN_FIND_VISUAL_STUDIO_BAT_FILE],
 [
+  # VS2017 provides the option to install previous minor versions of the MSVC
+  # toolsets. It is not possible to directly download earlier minor versions of
+  # VS2017 and in order to build with a previous minor compiler toolset version,
+  # it is now possible to compile with earlier minor versions by passing
+  # -vcvars_ver=<toolset_version> argument to vcvarsall.bat.
+  AC_ARG_WITH(msvc-toolset-version, [AS_HELP_STRING([--with-msvc-toolset-version],
+      [specific MSVC toolset version to use, passed as -vcvars_ver argument to
+       pass to vcvarsall.bat (Windows only)])])
+
   VS_VERSION="$1"
   eval VS_COMNTOOLS_VAR="\${VS_ENVVAR_${VS_VERSION}}"
   eval VS_COMNTOOLS="\$${VS_COMNTOOLS_VAR}"
@@ -184,6 +194,7 @@
   eval VS_EDITIONS="\${VS_EDITIONS_${VS_VERSION}}"
   eval SDK_INSTALL_DIR="\${VS_SDK_INSTALLDIR_${VS_VERSION}}"
   eval VS_ENV_ARGS="\${VS_ENV_ARGS_${VS_VERSION}}"
+  eval VS_TOOLSET_SUPPORTED="\${VS_TOOLSET_SUPPORTED_${VS_VERSION}}"
 
   # When using --with-tools-dir, assume it points to the correct and default
   # version of Visual Studio or that --with-toolchain-version was also set.
@@ -240,6 +251,12 @@
     TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT([${VS_VERSION}],
         [C:/Program Files (x86)/$SDK_INSTALL_DIR], [well-known name])
   fi
+
+  if test "x$VS_TOOLSET_SUPPORTED" != x; then
+    if test "x$with_msvc_toolset_version" != x; then
+      VS_ENV_ARGS="$VS_ENV_ARGS -vcvars_ver=$with_msvc_toolset_version"
+    fi
+  fi
 ])
 
 ################################################################################
@@ -423,6 +440,8 @@
             >> $EXTRACT_VC_ENV_BAT_FILE
         $ECHO 'echo VCINSTALLDIR="%VCINSTALLDIR% " >> set-vs-env.sh' \
             >> $EXTRACT_VC_ENV_BAT_FILE
+        $ECHO 'echo VCToolsRedistDir="%VCToolsRedistDir% " >> set-vs-env.sh' \
+            >> $EXTRACT_VC_ENV_BAT_FILE
         $ECHO 'echo WindowsSdkDir="%WindowsSdkDir% " >> set-vs-env.sh' \
             >> $EXTRACT_VC_ENV_BAT_FILE
         $ECHO 'echo WINDOWSSDKDIR="%WINDOWSSDKDIR% " >> set-vs-env.sh' \
@@ -440,6 +459,8 @@
             >> $EXTRACT_VC_ENV_BAT_FILE
         $ECHO "$WINPATH_BASH -c 'echo VCINSTALLDIR="'\"$VCINSTALLDIR \" >> set-vs-env.sh' \
             >> $EXTRACT_VC_ENV_BAT_FILE
+        $ECHO "$WINPATH_BASH -c 'echo VCToolsRedistDir="'\"$VCToolsRedistDir \" >> set-vs-env.sh' \
+            >> $EXTRACT_VC_ENV_BAT_FILE
         $ECHO "$WINPATH_BASH -c 'echo WindowsSdkDir="'\"$WindowsSdkDir \" >> set-vs-env.sh' \
             >> $EXTRACT_VC_ENV_BAT_FILE
         $ECHO "$WINPATH_BASH -c 'echo WINDOWSSDKDIR="'\"$WINDOWSSDKDIR \" >> set-vs-env.sh' \
@@ -517,6 +538,7 @@
       VS_INCLUDE=`$ECHO "$VS_INCLUDE" | $SED -e 's/\\\\*;* *$//'`
       VS_LIB=`$ECHO "$VS_LIB" | $SED 's/\\\\*;* *$//'`
       VCINSTALLDIR=`$ECHO "$VCINSTALLDIR" | $SED 's/\\\\* *$//'`
+      VCToolsRedistDir=`$ECHO "$VCToolsRedistDir" | $SED 's/\\\\* *$//'`
       WindowsSdkDir=`$ECHO "$WindowsSdkDir" | $SED 's/\\\\* *$//'`
       WINDOWSSDKDIR=`$ECHO "$WINDOWSSDKDIR" | $SED 's/\\\\* *$//'`
       if test -z "$WINDOWSSDKDIR"; then
@@ -638,11 +660,13 @@
           POSSIBLE_MSVC_DLL="$CYGWIN_VC_INSTALL_DIR/redist/x86/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME"
         fi
       else
+        CYGWIN_VC_TOOLS_REDIST_DIR="$VCToolsRedistDir"
+        BASIC_FIXUP_PATH(CYGWIN_VC_TOOLS_REDIST_DIR)
         # Probe: Using well-known location from VS 2017
         if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
-          POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_INSTALL_DIR/Redist/MSVC/*/x64/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
+          POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_TOOLS_REDIST_DIR/x64/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
         else
-          POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_INSTALL_DIR/Redist/MSVC/*/x86/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
+          POSSIBLE_MSVC_DLL="`ls $CYGWIN_VC_TOOLS_REDIST_DIR/x86/Microsoft.VC${VS_VERSION_INTERNAL}.CRT/$DLL_NAME`"
         fi
       fi
       # In case any of the above finds more than one file, loop over them.
--- a/make/conf/jib-profiles.js	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/conf/jib-profiles.js	Tue Mar 26 09:05:10 2019 -0400
@@ -939,21 +939,27 @@
 var getJibProfilesDependencies = function (input, common) {
 
     var devkit_platform_revisions = {
-        linux_x64: "gcc7.3.0-OEL6.4+1.2",
+        linux_x64: "gcc8.2.0-OL6.4+1.0",
         macosx_x64: "Xcode10.1-MacOSX10.14+1.0",
         solaris_x64: "SS12u4-Solaris11u1+1.0",
         solaris_sparcv9: "SS12u6-Solaris11u3+1.0",
         windows_x64: "VS2017-15.9.6+1.0",
-        linux_aarch64: "gcc7.3.0-Fedora27+1.2",
-        linux_arm: "gcc7.3.0-Fedora27+1.2",
-        linux_ppc64le: "gcc7.3.0-Fedora27+1.0",
-        linux_s390x: "gcc7.3.0-Fedora27+1.0"
+        linux_aarch64: "gcc8.2.0-Fedora27+1.0",
+        linux_arm: "gcc8.2.0-Fedora27+1.0",
+        linux_ppc64le: "gcc8.2.0-Fedora27+1.0",
+        linux_s390x: "gcc8.2.0-Fedora27+1.0"
     };
 
     var devkit_platform = (input.target_cpu == "x86"
         ? input.target_os + "_x64"
         : input.target_platform);
 
+    var devkit_cross_prefix = "";
+    if (input.build_platform != input.target_platform
+       && input.build_platform != devkit_platform) {
+        devkit_cross_prefix = input.build_platform + "-to-";
+    }
+
     var boot_jdk_platform = (input.build_os == "macosx" ? "osx" : input.build_os)
         + "-" + input.build_cpu;
     var boot_jdk_ext = (input.build_os == "windows" ? ".zip" : ".tar.gz")
@@ -984,7 +990,7 @@
         devkit: {
             organization: common.organization,
             ext: "tar.gz",
-            module: "devkit-" + devkit_platform,
+            module: "devkit-" + devkit_cross_prefix + devkit_platform,
             revision: devkit_platform_revisions[devkit_platform],
             environment: {
                 "DEVKIT_HOME": input.get("devkit", "home_path"),
--- a/make/data/charsetmapping/charsets	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/data/charsetmapping/charsets	Tue Mar 26 09:05:10 2019 -0400
@@ -440,6 +440,8 @@
     alias   cp00858
     alias   858
     alias   PC-Multilingual-850+euro
+    alias   ibm858
+    alias   ibm-858
 
 charset IBM862 IBM862
     package sun.nio.cs
@@ -1389,6 +1391,7 @@
      alias   cp833
      alias   ibm833
      alias   ibm-833
+     alias   833
 
 
 charset x-IBM834 IBM834 # EBCDIC DBCS-only Korean
@@ -1590,6 +1593,8 @@
     alias   cp01140
     alias   1140
     alias   ebcdic-us-037+euro
+    alias   ibm1140
+    alias   ibm-1140
 
 charset IBM01141 IBM1141
     package sun.nio.cs.ext
@@ -1601,6 +1606,8 @@
     alias   cp01141
     alias   1141
     alias   ebcdic-de-273+euro
+    alias   ibm1141
+    alias   ibm-1141
 
 charset IBM01142 IBM1142
     package sun.nio.cs.ext
@@ -1613,6 +1620,8 @@
     alias   1142
     alias   ebcdic-no-277+euro
     alias   ebcdic-dk-277+euro
+    alias   ibm1142
+    alias   ibm-1142
 
 charset IBM01143 IBM1143
     package sun.nio.cs.ext
@@ -1625,6 +1634,8 @@
     alias   1143
     alias   ebcdic-fi-278+euro
     alias   ebcdic-se-278+euro
+    alias   ibm1143
+    alias   ibm-1143
 
 charset IBM01144 IBM1144
     package sun.nio.cs.ext
@@ -1636,6 +1647,8 @@
     alias   cp01144
     alias   1144
     alias   ebcdic-it-280+euro
+    alias   ibm1144
+    alias   ibm-1144
 
 charset IBM01145 IBM1145
     package sun.nio.cs.ext
@@ -1647,6 +1660,8 @@
     alias   cp01145
     alias   1145
     alias   ebcdic-es-284+euro
+    alias   ibm1145
+    alias   ibm-1145
 
 charset IBM01146 IBM1146
     package sun.nio.cs.ext
@@ -1658,6 +1673,8 @@
     alias   cp01146
     alias   1146
     alias   ebcdic-gb-285+euro
+    alias   ibm1146
+    alias   ibm-1146
 
 charset IBM01147 IBM1147
     package sun.nio.cs.ext
@@ -1669,6 +1686,8 @@
     alias   cp01147
     alias   1147
     alias   ebcdic-fr-277+euro
+    alias   ibm1147
+    alias   ibm-1147
 
 charset IBM01148 IBM1148
     package sun.nio.cs.ext
@@ -1680,6 +1699,8 @@
     alias   cp01148
     alias   1148
     alias   ebcdic-international-500+euro
+    alias   ibm1148
+    alias   ibm-1148
 
 charset IBM01149 IBM1149
     package sun.nio.cs.ext
@@ -1691,6 +1712,8 @@
     alias   cp01149
     alias   1149
     alias   ebcdic-s-871+euro
+    alias   ibm1149
+    alias   ibm-1149
 
 charset IBM290 IBM290
     package sun.nio.cs.ext
--- a/make/devkit/Makefile	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/devkit/Makefile	Tue Mar 26 09:05:10 2019 -0400
@@ -29,14 +29,10 @@
 # gcc based cross compilation, portable, self contained packages, capable
 # of building OpenJDK.
 #
-# In addition to the makefiles, access to Oracle Linux installation
-# media is required. This has been tested against Oracle Enterprise Linux
-# 6.4.
-#
 # By default this Makefile will build a native toolchain for the current
 # platform if called with something like this:
 #
-# make tars BASE_OS=OEL6
+# make tars BASE_OS=OL
 #
 # To build the full set of crosstools for additional platforms, use a command
 # line looking like this:
@@ -48,9 +44,19 @@
 # to build several devkits for a specific OS version at once.
 # You can find the final results under ../../build/devkit/result/<host>-to-<target>
 #
+# You may want the native toolchain to be used when compiling the cross
+# compilation toolchains. To achieve this, first build the native toolchain,
+# then add the bin directory from this build to the path when invoking this
+# makefile again for cross compilation. Ex:
+#
+# PATH=$PWD/../../build/devkit/result/x86_64-linux-gnu-to-x86_64-linux-gnu/bin:$PATH \
+#    make TARGETS="arm-linux-gnueabihf,ppc64-linux-gnu" BASE_OS=Fedora
+#
 # This is the makefile which iterates over all host and target platforms.
 #
 
+COMMA := ,
+
 os := $(shell uname -o)
 cpu := $(shell uname -p)
 
@@ -66,7 +72,7 @@
   platforms := $(me)
   host_platforms := $(platforms)
 else
-  platforms := $(TARGETS)
+  platforms := $(subst $(COMMA), , $(TARGETS))
   host_platforms := $(me)
 endif
 target_platforms := $(platforms)
@@ -93,7 +99,7 @@
 	  $(MAKE) -f Tools.gmk all $(submakevars) \
               TARGET=$$p PREFIX=$(RESULT)/$@-to-$$p && \
 	  $(MAKE) -f Tools.gmk ccache $(submakevars) \
-              TARGET=$@ PREFIX=$(RESULT)/$@-to-$$p BUILDDIR=$(OUTPUT_ROOT)/$@/$$p || exit 1 ; \
+              TARGET=$@ PREFIX=$(RESULT)/$@-to-$$p || exit 1 ; \
 	done
 	@echo 'All done"'
 
@@ -103,7 +109,6 @@
   $(1)-to-$(2)_tar = $$(RESULT)/sdk-$(1)-to-$(2)-$$(today).tar.gz
   $$($(1)-to-$(2)_tar) : PLATFORM = $(1)-to-$(2)
   TARFILES += $$($(1)-to-$(2)_tar)
-  $$($(1)-to-$(2)_tar) : $$(shell find $$(RESULT)/$(1)-to-$(2) -type f)
 endef
 
 $(foreach p,$(host_platforms),$(foreach t,$(target_platforms),$(eval $(call Mktar,$(p),$(t)))))
@@ -111,9 +116,7 @@
 tars : all $(TARFILES)
 onlytars : $(TARFILES)
 %.tar.gz :
-	@echo 'Creating compiler package $@'
-	cd $(RESULT) && tar -czf $@ $(PLATFORM)/*
-	touch $@
+	$(MAKE) -r -f Tars.gmk SRC_DIR=$(RESULT)/$(PLATFORM) TAR_FILE=$@
 
 clean :
 	rm -rf $(addprefix ../../build/devkit/, result $(host_platforms))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/devkit/Tars.gmk	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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 makefile creates the tar files. It needs to be called with make -r
+# which is why it's separated out into its own file.
+
+# Input parameters
+# SRC_DIR
+# TAR_FILE
+
+ifeq ($(SRC_DIR), )
+  $(error SRC_DIR not set)
+endif
+ifeq ($(TAR_FILE), )
+  $(error TAR_FILE not set)
+endif
+
+default: tars
+
+tars : $(TAR_FILE)
+
+$(TAR_FILE): $(shell find $(SRC_DIR) -type f)
+	@echo 'Creating compiler package $@'
+	cd $(dir $(SRC_DIR)) && tar -czf $@ $(notdir $(SRC_DIR))/*
+	touch $@
+
+.PHONY: default tars
--- a/make/devkit/Tools.gmk	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/devkit/Tools.gmk	Tue Mar 26 09:05:10 2019 -0400
@@ -51,9 +51,9 @@
 
 $(info ARCH=$(ARCH))
 
-ifeq ($(BASE_OS), OEL6)
+ifeq ($(BASE_OS), OL)
   BASE_URL := http://yum.oracle.com/repo/OracleLinux/OL6/4/base/$(ARCH)/
-  LINUX_VERSION := OEL6.4
+  LINUX_VERSION := OL6.4
 else ifeq ($(BASE_OS), Fedora)
   DEFAULT_OS_VERSION := 27
   ifeq ($(BASE_OS_VERSION), )
@@ -79,8 +79,17 @@
 # Define external dependencies
 
 # Latest that could be made to work.
-GCC_VER := 7.3.0
-ifeq ($(GCC_VER), 7.3.0)
+GCC_VER := 8.2.0
+ifeq ($(GCC_VER), 8.2.0)
+  gcc_ver := gcc-8.2.0
+  binutils_ver := binutils-2.30
+  ccache_ver := ccache-3.5.1a
+  CCACHE_DIRNAME := ccache-3.5.1
+  mpfr_ver := mpfr-3.1.5
+  gmp_ver := gmp-6.1.2
+  mpc_ver := mpc-1.0.3
+  gdb_ver := gdb-8.2.1
+else ifeq ($(GCC_VER), 7.3.0)
   gcc_ver := gcc-7.3.0
   binutils_ver := binutils-2.30
   ccache_ver := ccache-3.3.6
@@ -174,14 +183,16 @@
 
 # Generate downloading + unpacking of sources.
 define Download
-  $(1)_DIR = $(abspath $(SRCDIR)/$(basename $(basename $(notdir $($(1))))))
+  # Allow override
+  $(1)_DIRNAME ?= $(basename $(basename $(notdir $($(1)))))
+  $(1)_DIR = $(abspath $(SRCDIR)/$$($(1)_DIRNAME))
   $(1)_CFG = $$($(1)_DIR)/configure
   $(1)_FILE = $(DOWNLOAD)/$(notdir $($(1)))
 
   $$($(1)_CFG) : $$($(1)_FILE)
 	mkdir -p $$(SRCDIR)
 	tar -C $$(SRCDIR) -xf $$<
-	$$(foreach p,$$(abspath $$(wildcard $$(notdir $$($(1)_DIR)).patch)), \
+	$$(foreach p,$$(abspath $$(wildcard patches/$$(notdir $$($(1)_DIR)).patch)), \
 	  echo PATCHING $$(p) ; \
 	  patch -d $$($(1)_DIR) -p1 -i $$(p) ; \
 	)
@@ -370,7 +381,7 @@
 	      --disable-nls \
 	      --program-prefix=$(TARGET)- \
 	      --enable-multilib \
-	      --enable-gold \
+	      --enable-gold=default \
 	      --enable-threads \
 	      --enable-plugins \
 	) > $(@D)/log.config 2>&1
--- a/make/hotspot/lib/JvmFeatures.gmk	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/hotspot/lib/JvmFeatures.gmk	Tue Mar 26 09:05:10 2019 -0400
@@ -47,6 +47,9 @@
 ifeq ($(call check-jvm-feature, zero), true)
   JVM_CFLAGS_FEATURES += -DZERO -DCC_INTERP -DZERO_LIBARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' $(LIBFFI_CFLAGS)
   JVM_LIBS_FEATURES += $(LIBFFI_LIBS)
+  ifeq ($(ENABLE_LIBFFI_BUNDLING), true)
+    JVM_LDFLAGS_FEATURES += $(call SET_EXECUTABLE_ORIGIN,/..)
+  endif
   ifeq ($(call isTargetCpu, sparcv9), true)
     BUILD_LIBJVM_EXTRA_FILES := $(TOPDIR)/src/hotspot/cpu/sparc/memset_with_concurrent_readers_sparc.cpp
   endif
--- a/make/lib/Awt2dLibraries.gmk	Tue Mar 26 08:57:28 2019 -0400
+++ b/make/lib/Awt2dLibraries.gmk	Tue Mar 26 09:05:10 2019 -0400
@@ -536,7 +536,8 @@
 
 ifeq ($(call isTargetOs, windows), false)
   HARFBUZZ_CFLAGS += -DGETPAGESIZE -DHAVE_MPROTECT -DHAVE_PTHREAD \
-                      -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H
+                      -DHAVE_SYSCONF -DHAVE_SYS_MMAN_H -DHAVE_UNISTD_H \
+                      -DHB_NO_PRAGMA_GCC_DIAGNOSTIC
 endif
 ifeq ($(call isTargetOs, linux macosx), true)
   HARFBUZZ_CFLAGS += -DHAVE_INTEL_ATOMIC_PRIMITIVES
@@ -613,8 +614,7 @@
         type-limits missing-field-initializers implicit-fallthrough \
         strict-aliasing undef unused-function, \
     DISABLED_WARNINGS_CXX_gcc := reorder delete-non-virtual-dtor strict-overflow \
-        maybe-uninitialized \
-        missing-attributes class-memaccess, \
+        maybe-uninitialized class-memaccess, \
     DISABLED_WARNINGS_clang := unused-value incompatible-pointer-types \
         tautological-constant-out-of-range-compare int-to-pointer-cast \
         sign-compare undef missing-field-initializers, \
@@ -624,8 +624,8 @@
         E_ENUM_VAL_OVERFLOWS_INT_MAX, \
     DISABLED_WARNINGS_CXX_solstudio := \
         truncwarn wvarhidenmem wvarhidemem wbadlkginit identexpected \
-        hidevf w_novirtualdescr arrowrtn2, \
-    DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334 4819 4101, \
+        hidevf w_novirtualdescr arrowrtn2 refmemnoconstr_aggr unknownpragma, \
+    DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334 4819 4101 4068 4805 4138, \
     LDFLAGS := $(subst -Xlinker -z -Xlinker defs,, \
         $(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB))) $(LDFLAGS_CXX_JDK) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/src/hotspot/cpu/aarch64/aarch64.ad	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/aarch64.ad	Tue Mar 26 09:05:10 2019 -0400
@@ -4246,7 +4246,7 @@
 %{
   // Get base of card map
   predicate(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) &&
-            (jbyte*)n->get_ptr() == ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base());
+            (CardTable::CardValue*)n->get_ptr() == ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base());
   match(ConP);
 
   op_cost(0);
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -72,15 +72,12 @@
 }
 
 void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                                             Register start, Register end, Register scratch, RegSet saved_regs) {
+                                                             Register start, Register count, Register scratch, RegSet saved_regs) {
   __ push(saved_regs, sp);
-  // must compute element count unless barrier set interface is changed (other platforms supply count)
-  assert_different_registers(start, end, scratch);
-  __ lea(scratch, Address(end, BytesPerHeapOop));
-  __ sub(scratch, scratch, start);               // subtract start to get #bytes
-  __ lsr(scratch, scratch, LogBytesPerHeapOop);  // convert to element count
+  assert_different_registers(start, count, scratch);
+  assert_different_registers(c_rarg0, count);
   __ mov(c_rarg0, start);
-  __ mov(c_rarg1, scratch);
+  __ mov(c_rarg1, count);
   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_post_entry), 2);
   __ pop(saved_regs, sp);
 }
@@ -193,7 +190,6 @@
   BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   Label done;
   Label runtime;
@@ -211,7 +207,6 @@
   // storing region crossing non-NULL, is card already dirty?
 
   ExternalAddress cardtable((address) ct->byte_map_base());
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
   const Register card_addr = tmp;
 
   __ lsr(card_addr, store_addr, CardTable::card_shift);
@@ -417,7 +412,6 @@
   BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   Label done;
   Label runtime;
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -39,7 +39,7 @@
   void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                        Register addr, Register count, RegSet saved_regs);
   void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                        Register start, Register end, Register tmp, RegSet saved_regs);
+                                        Register start, Register count, Register tmp, RegSet saved_regs);
 
   void g1_write_barrier_pre(MacroAssembler* masm,
                             Register obj,
--- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,6 @@
 
 #define __ masm->
 
-
 void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst) {
 
   BarrierSet* bs = BarrierSet::barrier_set();
@@ -40,7 +39,6 @@
 
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   __ lsr(obj, obj, CardTable::card_shift);
 
@@ -64,19 +62,22 @@
 }
 
 void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                                                    Register start, Register end, Register scratch, RegSet saved_regs) {
+                                                                    Register start, Register count, Register scratch, RegSet saved_regs) {
   BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+  Label L_loop, L_done;
+  const Register end = count;
 
-  Label L_loop;
+  __ cbz(count, L_done); // zero count - nothing to do
 
+  __ lea(end, Address(start, count, Address::lsl(LogBytesPerHeapOop))); // end = start + count << LogBytesPerHeapOop
+  __ sub(end, end, BytesPerHeapOop); // last element address to make inclusive
   __ lsr(start, start, CardTable::card_shift);
   __ lsr(end, end, CardTable::card_shift);
-  __ sub(end, end, start); // number of bytes to copy
+  __ sub(count, end, start); // number of bytes to copy
 
-  const Register count = end; // 'end' register contains bytes count now
   __ load_byte_map_base(scratch);
   __ add(start, start, scratch);
   if (ct->scanned_concurrently()) {
@@ -86,6 +87,7 @@
   __ strb(zr, Address(start, count));
   __ subs(count, count, 1);
   __ br(Assembler::GE, L_loop);
+  __ bind(L_done);
 }
 
 void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
--- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -33,7 +33,7 @@
   void store_check(MacroAssembler* masm, Register obj, Address dst);
 
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                                Register start, Register end, Register tmp, RegSet saved_regs);
+                                                Register start, Register count, Register tmp, RegSet saved_regs);
   virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                             Address dst, Register val, Register tmp1, Register tmp2);
 
--- a/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -37,10 +37,10 @@
 }
 
 void ModRefBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
-                                                   Register start, Register end, Register tmp,
+                                                   Register start, Register count, Register tmp,
                                                    RegSet saved_regs) {
   if (is_oop) {
-    gen_write_ref_array_post_barrier(masm, decorators, start, end, tmp, saved_regs);
+    gen_write_ref_array_post_barrier(masm, decorators, start, count, tmp, saved_regs);
   }
 }
 
--- a/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -37,7 +37,7 @@
   virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                Register addr, Register count, RegSet saved_regs) {}
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                                Register start, Register end, Register tmp, RegSet saved_regs) {}
+                                                Register start, Register count, Register tmp, RegSet saved_regs) {}
 
   virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                             Address dst, Register val, Register tmp1, Register tmp2) = 0;
@@ -46,7 +46,7 @@
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
                                   Register addr, Register count, RegSet saved_regs);
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
-                                  Register start, Register end, Register tmp, RegSet saved_regs);
+                                  Register start, Register count, Register tmp, RegSet saved_regs);
   virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                         Address dst, Register val, Register tmp1, Register tmp2);
 };
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -73,16 +73,13 @@
 }
 
 void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
-                                                       Register start, Register end, Register scratch, RegSet saved_regs) {
+                                                       Register start, Register count, Register scratch, RegSet saved_regs) {
   if (is_oop) {
     __ push(saved_regs, sp);
-    // must compute element count unless barrier set interface is changed (other platforms supply count)
-    assert_different_registers(start, end, scratch);
-    __ lea(scratch, Address(end, BytesPerHeapOop));
-    __ sub(scratch, scratch, start);               // subtract start to get #bytes
-    __ lsr(scratch, scratch, LogBytesPerHeapOop);  // convert to element count
+    assert_different_registers(start, count, scratch);
+    assert_different_registers(c_rarg0, count);
     __ mov(c_rarg0, start);
-    __ mov(c_rarg1, scratch);
+    __ mov(c_rarg1, count);
     __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_array_post_entry), 2);
     __ pop(saved_regs, sp);
   }
--- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -78,7 +78,7 @@
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
                                   Register addr, Register count, RegSet saved_regs);
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
-                                  Register start, Register end, Register tmp, RegSet saved_regs);
+                                  Register start, Register count, Register tmp, RegSet saved_regs);
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                        Register dst, Address src, Register tmp1, Register tmp_thread);
   virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -4305,7 +4305,7 @@
 }
 
 void MacroAssembler::load_byte_map_base(Register reg) {
-  jbyte *byte_map_base =
+  CardTable::CardValue* byte_map_base =
     ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base();
 
   if (is_valid_AArch64_address((address)byte_map_base)) {
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1375,8 +1375,6 @@
       __ pop(RegSet::of(d, count), sp);
       if (VerifyOops)
         verify_oop_array(size, d, count, r16);
-      __ sub(count, count, 1); // make an inclusive end pointer
-      __ lea(count, Address(d, count, Address::lsl(exact_log2(size))));
     }
 
     bs->arraycopy_epilogue(_masm, decorators, is_oop, d, count, rscratch1, RegSet());
@@ -1448,8 +1446,6 @@
       __ pop(RegSet::of(d, count), sp);
       if (VerifyOops)
         verify_oop_array(size, d, count, r16);
-      __ sub(count, count, 1); // make an inclusive end pointer
-      __ lea(count, Address(d, count, Address::lsl(exact_log2(size))));
     }
     bs->arraycopy_epilogue(_masm, decorators, is_oop, d, count, rscratch1, RegSet());
     __ leave();
@@ -1842,8 +1838,7 @@
     __ br(Assembler::EQ, L_done_pop);
 
     __ BIND(L_do_card_marks);
-    __ add(to, to, -heapOopSize);         // make an inclusive end pointer
-    bs->arraycopy_epilogue(_masm, decorators, is_oop, start_to, to, rscratch1, wb_post_saved_regs);
+    bs->arraycopy_epilogue(_masm, decorators, is_oop, start_to, count_save, rscratch1, wb_post_saved_regs);
 
     __ bind(L_done_pop);
     __ pop(RegSet::of(r18, r19, r20, r21), sp);
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -2885,7 +2885,7 @@
   {
     Label notVolatile;
     __ tbz(r5, ConstantPoolCacheEntry::is_volatile_shift, notVolatile);
-    __ membar(MacroAssembler::StoreLoad);
+    __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore);
     __ bind(notVolatile);
   }
 }
@@ -3029,7 +3029,7 @@
   {
     Label notVolatile;
     __ tbz(r3, ConstantPoolCacheEntry::is_volatile_shift, notVolatile);
-    __ membar(MacroAssembler::StoreLoad);
+    __ membar(MacroAssembler::StoreLoad | MacroAssembler::StoreStore);
     __ bind(notVolatile);
   }
 }
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -194,6 +194,19 @@
 
   // Enable vendor specific features
 
+  // Ampere eMAG
+  if (_cpu == CPU_AMCC && (_model == 0) && (_variant == 0x3)) {
+    if (FLAG_IS_DEFAULT(AvoidUnalignedAccesses)) {
+      FLAG_SET_DEFAULT(AvoidUnalignedAccesses, true);
+    }
+    if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) {
+      FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true);
+    }
+    if (FLAG_IS_DEFAULT(UseSIMDForArrayEquals)) {
+      FLAG_SET_DEFAULT(UseSIMDForArrayEquals, !(_revision == 1 || _revision == 2));
+    }
+  }
+
   // ThunderX
   if (_cpu == CPU_CAVIUM && (_model == 0xA1)) {
     if (_variant == 0) _features |= CPU_DMB_ATOMICS;
--- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -216,7 +216,6 @@
 
   // storing region crossing non-NULL, is card already dirty?
   const Register card_addr = tmp1;
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   __ mov_address(tmp2, (address)ct->byte_map_base());
   __ add(card_addr, tmp2, AsmOperand(store_addr, lsr, CardTable::card_shift));
--- a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -47,7 +47,6 @@
   BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   Label L_cardtable_loop, L_done;
 
@@ -102,7 +101,6 @@
 
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "Adjust store check code");
 
   // Load card table base address.
 
@@ -132,7 +130,6 @@
 
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "Adjust store check code");
 
   assert(CardTable::dirty_card_val() == 0, "Dirty card value must be 0 due to optimizations.");
   Address card_table_addr(card_table_base, obj, lsr, CardTable::card_shift);
--- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1455,13 +1455,11 @@
           break;
       }
     } else {
-      if (opr2->is_address()) {
-        DEBUG_ONLY( Unimplemented(); ) // Seems to be unused at the moment.
-        LIR_Address *addr = opr2->as_address_ptr();
-        BasicType type = addr->type();
-        if (type == T_OBJECT) { __ ld(R0, index_or_disp(addr), addr->base()->as_register()); }
-        else                  { __ lwa(R0, index_or_disp(addr), addr->base()->as_register()); }
-        __ cmpd(BOOL_RESULT, opr1->as_register(), R0);
+      assert(opr1->type() != T_ADDRESS && opr2->type() != T_ADDRESS, "currently unsupported");
+      if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) {
+        // There are only equal/notequal comparisons on objects.
+        assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "oops");
+        __ cmpd(BOOL_RESULT, opr1->as_register(), opr2->as_register());
       } else {
         if (unsigned_comp) {
           __ cmplw(BOOL_RESULT, opr1->as_register(), opr2->as_register());
@@ -1497,14 +1495,6 @@
     } else {
       ShouldNotReachHere();
     }
-  } else if (opr1->is_address()) {
-    DEBUG_ONLY( Unimplemented(); ) // Seems to be unused at the moment.
-    LIR_Address * addr = opr1->as_address_ptr();
-    BasicType type = addr->type();
-    assert (opr2->is_constant(), "Checking");
-    if (type == T_OBJECT) { __ ld(R0, index_or_disp(addr), addr->base()->as_register()); }
-    else                  { __ lwa(R0, index_or_disp(addr), addr->base()->as_register()); }
-    __ cmpdi(BOOL_RESULT, R0, opr2->as_constant_ptr()->as_jint());
   } else {
     ShouldNotReachHere();
   }
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -213,7 +213,6 @@
   assert_different_registers(store_addr, new_val, tmp1, tmp2);
 
   CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
-  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   // Does store cross heap regions?
   __ xorr(tmp1, store_addr, new_val);
@@ -478,7 +477,7 @@
   Register tmp = R0;
   Register addr = R14;
   Register tmp2 = R15;
-  jbyte* byte_map_base = bs->card_table()->byte_map_base();
+  CardTable::CardValue* byte_map_base = bs->card_table()->byte_map_base();
 
   Label restart, refill, ret;
 
--- a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -45,7 +45,6 @@
                                                                     Register count, Register preserve) {
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
   assert_different_registers(addr, count, R0);
 
   Label Lskip_loop, Lstore_loop;
@@ -73,7 +72,7 @@
 }
 
 void CardTableBarrierSetAssembler::card_table_write(MacroAssembler* masm,
-                                                    jbyte* byte_map_base,
+                                                    CardTable::CardValue* byte_map_base,
                                                     Register tmp, Register obj) {
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
--- a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -34,7 +34,7 @@
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                 Register addr, Register count, Register preserve);
 
-  void card_table_write(MacroAssembler* masm, jbyte* byte_map_base, Register tmp, Register obj);
+  void card_table_write(MacroAssembler* masm, CardTable::CardValue* byte_map_base, Register tmp, Register obj);
 
   void card_write_barrier_post(MacroAssembler* masm, Register store_addr, Register tmp);
 
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -269,7 +269,6 @@
   Label callRuntime, filtered;
 
   CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
-  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   BLOCK_COMMENT("g1_write_barrier_post {");
 
@@ -298,7 +297,6 @@
   Rnew_val = noreg; // end of lifetime
 
   // Storing region crossing non-NULL, is card already dirty?
-  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
   assert_different_registers(Rtmp1, Rtmp2, Rtmp3);
   // Make sure not to use Z_R0 for any of these registers.
   Register Rcard_addr = (Rtmp1 != Z_R0_scratch) ? Rtmp1 : Rtmp3;
@@ -311,14 +309,12 @@
   Rbase = noreg; // end of lifetime
 
   // Filter young.
-  assert((unsigned int)G1CardTable::g1_young_card_val() <= 255, "otherwise check this code");
   __ z_cli(0, Rcard_addr, G1CardTable::g1_young_card_val());
   __ z_bre(filtered);
 
   // Check the card value. If dirty, we're done.
   // This also avoids false sharing of the (already dirty) card.
   __ z_sync(); // Required to support concurrent cleaning.
-  assert((unsigned int)G1CardTable::dirty_card_val() <= 255, "otherwise check this code");
   __ z_cli(0, Rcard_addr, G1CardTable::dirty_card_val()); // Reload after membar.
   __ z_bre(filtered);
 
@@ -542,7 +538,7 @@
   Register cardtable = r1;   // Must be non-volatile, because it is used to save addr_card.
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  jbyte* byte_map_base = ct->byte_map_base();
+  CardTable::CardValue* byte_map_base = ct->byte_map_base();
 
   // Save registers used below (see assertion in G1PreBarrierStub::emit_code()).
   __ z_stg(r1, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
--- a/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -47,7 +47,6 @@
                                                                     bool do_return) {
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   NearLabel doXC, done;
   assert_different_registers(Z_R0, Z_R1, addr, count);
@@ -144,7 +143,6 @@
   // register obj is destroyed afterwards.
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   assert_different_registers(store_addr, tmp);
 
--- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -275,7 +275,7 @@
 static u_char* dirty_card_log_enqueue_end = 0;
 
 // This gets to assume that o0 contains the object address.
-static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) {
+static void generate_dirty_card_log_enqueue(CardTable::CardValue* byte_map_base) {
   BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2);
   CodeBuffer buf(bb);
   MacroAssembler masm(&buf);
@@ -626,7 +626,7 @@
   Register cardtable = G5;
   Register tmp  = G1_scratch;
   Register tmp2 = G3_scratch;
-  jbyte* byte_map_base = bs->card_table()->byte_map_base();
+  CardTable::CardValue* byte_map_base = bs->card_table()->byte_map_base();
 
   Label not_already_dirty, restart, refill, young_card;
 
--- a/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -44,7 +44,6 @@
                                                                     Register addr, Register count, Register tmp) {
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
   assert_different_registers(addr, count, tmp);
 
   Label L_loop, L_done;
@@ -70,7 +69,7 @@
 }
 
 void CardTableBarrierSetAssembler::card_table_write(MacroAssembler* masm,
-                                                    jbyte* byte_map_base,
+                                                    CardTable::CardValue* byte_map_base,
                                                     Register tmp, Register obj) {
   __ srlx(obj, CardTable::card_shift, obj);
   assert(tmp != obj, "need separate temp reg");
--- a/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -26,6 +26,7 @@
 #define CPU_SPARC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_SPARC_HPP
 
 #include "asm/macroAssembler.hpp"
+#include "gc/shared/cardTable.hpp"
 #include "gc/shared/modRefBarrierSetAssembler.hpp"
 
 class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
@@ -33,7 +34,7 @@
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                 Register addr, Register count, Register tmp);
 
-  void card_table_write(MacroAssembler* masm, jbyte* byte_map_base, Register tmp, Register obj);
+  void card_table_write(MacroAssembler* masm, CardTable::CardValue* byte_map_base, Register tmp, Register obj);
 
   void card_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, Register tmp);
 
--- a/src/hotspot/cpu/x86/crc32c.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/x86/crc32c.h	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,9 @@
 *
 */
 
+#ifndef CPU_X86_CRC32C_H
+#define CPU_X86_CRC32C_H
+
 enum {
   // S. Gueron / Information Processing Letters 112 (2012) 184
   // shows than anything above 6K and below 32K is a good choice
@@ -64,3 +67,5 @@
 // a) constants table generation (hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp)
 // b) constant fetch from that table (macroAssembler_x86.cpp)
 // c) unrolled for loop (macroAssembler_x86.cpp)
+
+#endif /* !CPU_X86_CRC32C_H */
--- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -273,7 +273,6 @@
 
   CardTableBarrierSet* ct =
     barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
-  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   Label done;
   Label runtime;
@@ -522,7 +521,6 @@
 
   CardTableBarrierSet* ct =
     barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
-  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   Label done;
   Label enqueued;
--- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -46,7 +46,6 @@
   BarrierSet *bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
   intptr_t disp = (intptr_t) ct->byte_map_base();
 
   Label L_loop, L_done;
@@ -92,7 +91,6 @@
 
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
   __ shrptr(obj, CardTable::card_shift);
 
--- a/src/hotspot/cpu/x86/x86_32.ad	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/x86/x86_32.ad	Tue Mar 26 09:05:10 2019 -0400
@@ -391,7 +391,7 @@
         int format) {
 #ifdef ASSERT
   if (rspec.reloc()->type() == relocInfo::oop_type && d32 != 0 && d32 != (int)Universe::non_oop_word()) {
-    assert(oopDesc::is_oop(cast_to_oop(d32)) && (ScavengeRootsInCode || !Universe::heap()->is_scavengable(cast_to_oop(d32))), "cannot embed scavengable oops in code");
+    assert(oopDesc::is_oop(cast_to_oop(d32)), "cannot embed broken oops in code");
   }
 #endif
   cbuf.relocate(cbuf.insts_mark(), rspec, format);
--- a/src/hotspot/cpu/x86/x86_64.ad	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/cpu/x86/x86_64.ad	Tue Mar 26 09:05:10 2019 -0400
@@ -547,7 +547,7 @@
   if (rspec.reloc()->type() == relocInfo::oop_type &&
       d32 != 0 && d32 != (intptr_t) Universe::non_oop_word()) {
     assert(Universe::heap()->is_in_reserved((address)(intptr_t)d32), "should be real oop");
-    assert(oopDesc::is_oop(cast_to_oop((intptr_t)d32)) && (ScavengeRootsInCode || !Universe::heap()->is_scavengable(cast_to_oop((intptr_t)d32))), "cannot embed scavengable oops in code");
+    assert(oopDesc::is_oop(cast_to_oop((intptr_t)d32)), "cannot embed broken oops in code");
   }
 #endif
   cbuf.relocate(cbuf.insts_mark(), rspec, format);
@@ -574,8 +574,7 @@
   if (rspec.reloc()->type() == relocInfo::oop_type &&
       d64 != 0 && d64 != (int64_t) Universe::non_oop_word()) {
     assert(Universe::heap()->is_in_reserved((address)d64), "should be real oop");
-    assert(oopDesc::is_oop(cast_to_oop(d64)) && (ScavengeRootsInCode || !Universe::heap()->is_scavengable(cast_to_oop(d64))),
-           "cannot embed scavengable oops in code");
+    assert(oopDesc::is_oop(cast_to_oop(d64)), "cannot embed broken oops in code");
   }
 #endif
   cbuf.relocate(cbuf.insts_mark(), rspec, format);
--- a/src/hotspot/os/aix/os_aix.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/aix/os_aix.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -37,6 +37,7 @@
 #include "compiler/compileBroker.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "libo4.hpp"
 #include "libperfstat_aix.hpp"
 #include "libodm_aix.hpp"
@@ -923,6 +924,11 @@
     char buf[64];
     log_warning(os, thread)("Failed to start thread - pthread_create failed (%d=%s) for attributes: %s.",
       ret, os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
+    // Log some OS information which might explain why creating the thread failed.
+    log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+    LogStream st(Log(os, thread)::info());
+    os::Posix::print_rlimit_info(&st);
+    os::print_memory_info(&st);
   }
 
   pthread_attr_destroy(&attr);
--- a/src/hotspot/os/bsd/os_bsd.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/bsd/os_bsd.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -33,6 +33,7 @@
 #include "compiler/disassembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/filemap.hpp"
 #include "oops/oop.inline.hpp"
@@ -743,6 +744,11 @@
     } else {
       log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.",
         os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
+      // Log some OS information which might explain why creating the thread failed.
+      log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+      LogStream st(Log(os, thread)::info());
+      os::Posix::print_rlimit_info(&st);
+      os::print_memory_info(&st);
     }
 
     pthread_attr_destroy(&attr);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zLargePages_linux.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zLargePages.hpp"
+#include "runtime/globals.hpp"
+
+void ZLargePages::initialize_platform() {
+  if (UseLargePages) {
+    if (UseTransparentHugePages) {
+      _state = Transparent;
+    } else {
+      _state = Explicit;
+    }
+  } else {
+    _state = Disabled;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "gc/z/zErrno.hpp"
+#include "gc/z/zCPU.hpp"
+#include "gc/z/zNUMA.hpp"
+#include "runtime/os.hpp"
+#include "utilities/debug.hpp"
+
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#ifndef MPOL_F_NODE
+#define MPOL_F_NODE     (1<<0)  // Return next IL mode instead of node mask
+#endif
+
+#ifndef MPOL_F_ADDR
+#define MPOL_F_ADDR     (1<<1)  // Look up VMA using address
+#endif
+
+static int z_get_mempolicy(uint32_t* mode, const unsigned long *nmask, unsigned long maxnode, uintptr_t addr, int flags) {
+  return syscall(__NR_get_mempolicy, mode, nmask, maxnode, addr, flags);
+}
+
+void ZNUMA::initialize_platform() {
+  _enabled = UseNUMA;
+}
+
+uint32_t ZNUMA::count() {
+  if (!_enabled) {
+    // NUMA support not enabled
+    return 1;
+  }
+
+  return os::Linux::numa_max_node() + 1;
+}
+
+uint32_t ZNUMA::id() {
+  if (!_enabled) {
+    // NUMA support not enabled
+    return 0;
+  }
+
+  return os::Linux::get_node_by_cpu(ZCPU::id());
+}
+
+uint32_t ZNUMA::memory_id(uintptr_t addr) {
+  if (!_enabled) {
+    // NUMA support not enabled, assume everything belongs to node zero
+    return 0;
+  }
+
+  uint32_t id = (uint32_t)-1;
+
+  if (z_get_mempolicy(&id, NULL, 0, addr, MPOL_F_NODE | MPOL_F_ADDR) == -1) {
+    ZErrno err;
+    fatal("Failed to get NUMA id for memory at " PTR_FORMAT " (%s)", addr, err.to_string());
+  }
+
+  assert(id < count(), "Invalid NUMA id");
+
+  return id;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/os/linux/gc/z/zVirtualMemory_linux.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zVirtualMemory.hpp"
+#include "logging/log.hpp"
+
+#include <sys/mman.h>
+#include <sys/types.h>
+
+bool ZVirtualMemoryManager::reserve(uintptr_t start, size_t size) {
+  // Reserve address space
+  const uintptr_t actual_start = (uintptr_t)mmap((void*)start, size, PROT_NONE,
+                                                 MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
+  if (actual_start != start) {
+    log_error(gc)("Failed to reserve address space for Java heap");
+    return false;
+  }
+
+  return true;
+}
--- a/src/hotspot/os/linux/osContainer_linux.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/linux/osContainer_linux.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -99,14 +99,14 @@
             buf[MAXPATHLEN-1] = '\0';
             _path = os::strdup(buf);
           } else {
-            char *p = strstr(_root, cgroup_path);
+            char *p = strstr(cgroup_path, _root);
             if (p != NULL && p == _root) {
               if (strlen(cgroup_path) > strlen(_root)) {
                 int buflen;
                 strncpy(buf, _mount_point, MAXPATHLEN);
                 buf[MAXPATHLEN-1] = '\0';
                 buflen = strlen(buf);
-                if ((buflen + strlen(cgroup_path)) > (MAXPATHLEN-1)) {
+                if ((buflen + strlen(cgroup_path) - strlen(_root)) > (MAXPATHLEN-1)) {
                   return;
                 }
                 strncat(buf, cgroup_path + strlen(_root), MAXPATHLEN-buflen);
@@ -217,16 +217,11 @@
  * we are running under cgroup control.
  */
 void OSContainer::init() {
-  int mountid;
-  int parentid;
-  int major;
-  int minor;
   FILE *mntinfo = NULL;
   FILE *cgroup = NULL;
   char buf[MAXPATHLEN+1];
   char tmproot[MAXPATHLEN+1];
   char tmpmount[MAXPATHLEN+1];
-  char tmpbase[MAXPATHLEN+1];
   char *p;
   jlong mem_limit;
 
@@ -260,85 +255,24 @@
       return;
   }
 
-  while ( (p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) {
-    // Look for the filesystem type and see if it's cgroup
-    char fstype[MAXPATHLEN+1];
-    fstype[0] = '\0';
-    char *s =  strstr(p, " - ");
-    if (s != NULL &&
-        sscanf(s, " - %s", fstype) == 1 &&
-        strcmp(fstype, "cgroup") == 0) {
+  while ((p = fgets(buf, MAXPATHLEN, mntinfo)) != NULL) {
+    char tmpcgroups[MAXPATHLEN+1];
+    char *cptr = tmpcgroups;
+    char *token;
 
-      if (strstr(p, "memory") != NULL) {
-        int matched = sscanf(p, "%d %d %d:%d %s %s",
-                             &mountid,
-                             &parentid,
-                             &major,
-                             &minor,
-                             tmproot,
-                             tmpmount);
-        if (matched == 6) {
-          memory = new CgroupSubsystem(tmproot, tmpmount);
-        }
-        else
-          log_debug(os, container)("Incompatible str containing cgroup and memory: %s", p);
-      } else if (strstr(p, "cpuset") != NULL) {
-        int matched = sscanf(p, "%d %d %d:%d %s %s",
-                             &mountid,
-                             &parentid,
-                             &major,
-                             &minor,
-                             tmproot,
-                             tmpmount);
-        if (matched == 6) {
-          cpuset = new CgroupSubsystem(tmproot, tmpmount);
-        }
-        else {
-          log_debug(os, container)("Incompatible str containing cgroup and cpuset: %s", p);
-        }
-      } else if (strstr(p, "cpu,cpuacct") != NULL || strstr(p, "cpuacct,cpu") != NULL) {
-        int matched = sscanf(p, "%d %d %d:%d %s %s",
-                             &mountid,
-                             &parentid,
-                             &major,
-                             &minor,
-                             tmproot,
-                             tmpmount);
-        if (matched == 6) {
-          cpu = new CgroupSubsystem(tmproot, tmpmount);
-          cpuacct = new CgroupSubsystem(tmproot, tmpmount);
-        }
-        else {
-          log_debug(os, container)("Incompatible str containing cgroup and cpu,cpuacct: %s", p);
-        }
-      } else if (strstr(p, "cpuacct") != NULL) {
-        int matched = sscanf(p, "%d %d %d:%d %s %s",
-                             &mountid,
-                             &parentid,
-                             &major,
-                             &minor,
-                             tmproot,
-                             tmpmount);
-        if (matched == 6) {
-          cpuacct = new CgroupSubsystem(tmproot, tmpmount);
-        }
-        else {
-          log_debug(os, container)("Incompatible str containing cgroup and cpuacct: %s", p);
-        }
-      } else if (strstr(p, "cpu") != NULL) {
-        int matched = sscanf(p, "%d %d %d:%d %s %s",
-                             &mountid,
-                             &parentid,
-                             &major,
-                             &minor,
-                             tmproot,
-                             tmpmount);
-        if (matched == 6) {
-          cpu = new CgroupSubsystem(tmproot, tmpmount);
-        }
-        else {
-          log_debug(os, container)("Incompatible str containing cgroup and cpu: %s", p);
-        }
+    // mountinfo format is documented at https://www.kernel.org/doc/Documentation/filesystems/proc.txt
+    if (sscanf(p, "%*d %*d %*d:%*d %s %s %*[^-]- cgroup %*s %s", tmproot, tmpmount, tmpcgroups) != 3) {
+      continue;
+    }
+    while ((token = strsep(&cptr, ",")) != NULL) {
+      if (strcmp(token, "memory") == 0) {
+        memory = new CgroupSubsystem(tmproot, tmpmount);
+      } else if (strcmp(token, "cpuset") == 0) {
+        cpuset = new CgroupSubsystem(tmproot, tmpmount);
+      } else if (strcmp(token, "cpu") == 0) {
+        cpu = new CgroupSubsystem(tmproot, tmpmount);
+      } else if (strcmp(token, "cpuacct") == 0) {
+        cpuacct= new CgroupSubsystem(tmproot, tmpmount);
       }
     }
   }
@@ -392,30 +326,30 @@
     return;
   }
 
-  while ( (p = fgets(buf, MAXPATHLEN, cgroup)) != NULL) {
-    int cgno;
-    int matched;
-    char *controller;
+  while ((p = fgets(buf, MAXPATHLEN, cgroup)) != NULL) {
+    char *controllers;
+    char *token;
     char *base;
 
     /* Skip cgroup number */
     strsep(&p, ":");
-    /* Get controller and base */
-    controller = strsep(&p, ":");
+    /* Get controllers and base */
+    controllers = strsep(&p, ":");
     base = strsep(&p, "\n");
 
-    if (controller != NULL) {
-      if (strstr(controller, "memory") != NULL) {
+    if (controllers == NULL) {
+      continue;
+    }
+
+    while ((token = strsep(&controllers, ",")) != NULL) {
+      if (strcmp(token, "memory") == 0) {
         memory->set_subsystem_path(base);
-      } else if (strstr(controller, "cpuset") != NULL) {
+      } else if (strcmp(token, "cpuset") == 0) {
         cpuset->set_subsystem_path(base);
-      } else if (strstr(controller, "cpu,cpuacct") != NULL || strstr(controller, "cpuacct,cpu") != NULL) {
+      } else if (strcmp(token, "cpu") == 0) {
         cpu->set_subsystem_path(base);
+      } else if (strcmp(token, "cpuacct") == 0) {
         cpuacct->set_subsystem_path(base);
-      } else if (strstr(controller, "cpuacct") != NULL) {
-        cpuacct->set_subsystem_path(base);
-      } else if (strstr(controller, "cpu") != NULL) {
-        cpu->set_subsystem_path(base);
       }
     }
   }
--- a/src/hotspot/os/linux/os_linux.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/linux/os_linux.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -780,6 +780,13 @@
     } else {
       log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.",
         os::errno_name(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr));
+      // Log some OS information which might explain why creating the thread failed.
+      log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+      LogStream st(Log(os, thread)::info());
+      os::Posix::print_rlimit_info(&st);
+      os::print_memory_info(&st);
+      os::Linux::print_proc_sys_info(&st);
+      os::Linux::print_container_info(&st);
     }
 
     pthread_attr_destroy(&attr);
@@ -2140,46 +2147,87 @@
   st->print("container (cgroup) information:\n");
 
   const char *p_ct = OSContainer::container_type();
-  st->print("container_type: %s\n", p_ct != NULL ? p_ct : "failed");
+  st->print("container_type: %s\n", p_ct != NULL ? p_ct : "not supported");
 
   char *p = OSContainer::cpu_cpuset_cpus();
-  st->print("cpu_cpuset_cpus: %s\n", p != NULL ? p : "failed");
+  st->print("cpu_cpuset_cpus: %s\n", p != NULL ? p : "not supported");
   free(p);
 
   p = OSContainer::cpu_cpuset_memory_nodes();
-  st->print("cpu_memory_nodes: %s\n", p != NULL ? p : "failed");
+  st->print("cpu_memory_nodes: %s\n", p != NULL ? p : "not supported");
   free(p);
 
   int i = OSContainer::active_processor_count();
+  st->print("active_processor_count: ");
   if (i > 0) {
-    st->print("active_processor_count: %d\n", i);
+    st->print("%d\n", i);
   } else {
-    st->print("active_processor_count: failed\n");
+    st->print("not supported\n");
   }
 
   i = OSContainer::cpu_quota();
-  st->print("cpu_quota: %d\n", i);
+  st->print("cpu_quota: ");
+  if (i > 0) {
+    st->print("%d\n", i);
+  } else {
+    st->print("%s\n", i == OSCONTAINER_ERROR ? "not supported" : "no quota");
+  }
 
   i = OSContainer::cpu_period();
-  st->print("cpu_period: %d\n", i);
+  st->print("cpu_period: ");
+  if (i > 0) {
+    st->print("%d\n", i);
+  } else {
+    st->print("%s\n", i == OSCONTAINER_ERROR ? "not supported" : "no period");
+  }
 
   i = OSContainer::cpu_shares();
-  st->print("cpu_shares: %d\n", i);
+  st->print("cpu_shares: ");
+  if (i > 0) {
+    st->print("%d\n", i);
+  } else {
+    st->print("%s\n", i == OSCONTAINER_ERROR ? "not supported" : "no shares");
+  }
 
   jlong j = OSContainer::memory_limit_in_bytes();
-  st->print("memory_limit_in_bytes: " JLONG_FORMAT "\n", j);
+  st->print("memory_limit_in_bytes: ");
+  if (j > 0) {
+    st->print(JLONG_FORMAT "\n", j);
+  } else {
+    st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+  }
 
   j = OSContainer::memory_and_swap_limit_in_bytes();
-  st->print("memory_and_swap_limit_in_bytes: " JLONG_FORMAT "\n", j);
+  st->print("memory_and_swap_limit_in_bytes: ");
+  if (j > 0) {
+    st->print(JLONG_FORMAT "\n", j);
+  } else {
+    st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+  }
 
   j = OSContainer::memory_soft_limit_in_bytes();
-  st->print("memory_soft_limit_in_bytes: " JLONG_FORMAT "\n", j);
+  st->print("memory_soft_limit_in_bytes: ");
+  if (j > 0) {
+    st->print(JLONG_FORMAT "\n", j);
+  } else {
+    st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+  }
 
   j = OSContainer::OSContainer::memory_usage_in_bytes();
-  st->print("memory_usage_in_bytes: " JLONG_FORMAT "\n", j);
+  st->print("memory_usage_in_bytes: ");
+  if (j > 0) {
+    st->print(JLONG_FORMAT "\n", j);
+  } else {
+    st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+  }
 
   j = OSContainer::OSContainer::memory_max_usage_in_bytes();
-  st->print("memory_max_usage_in_bytes: " JLONG_FORMAT "\n", j);
+  st->print("memory_max_usage_in_bytes: ");
+  if (j > 0) {
+    st->print(JLONG_FORMAT "\n", j);
+  } else {
+    st->print("%s\n", j == OSCONTAINER_ERROR ? "not supported" : "unlimited");
+  }
   st->cr();
 }
 
@@ -2292,7 +2340,7 @@
 #elif defined(PPC64)
 const char* search_string = "cpu";
 #elif defined(S390)
-const char* search_string = "processor";
+const char* search_string = "machine =";
 #elif defined(SPARC)
 const char* search_string = "cpu";
 #else
--- a/src/hotspot/os/posix/os_posix.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1671,6 +1671,8 @@
   if ((status = pthread_mutexattr_settype(_mutexAttr, PTHREAD_MUTEX_NORMAL)) != 0) {
     fatal("pthread_mutexattr_settype: %s", os::strerror(status));
   }
+  // Solaris has it's own PlatformMonitor, distinct from the one for POSIX.
+  NOT_SOLARIS(os::PlatformMonitor::init();)
 }
 
 #ifndef SOLARIS
@@ -2250,20 +2252,64 @@
 
 // Platform Monitor implementation
 
-os::PlatformMonitor::PlatformMonitor() {
+os::PlatformMonitor::Impl::Impl() : _next(NULL) {
   int status = pthread_cond_init(&_cond, _condAttr);
   assert_status(status == 0, status, "cond_init");
   status = pthread_mutex_init(&_mutex, _mutexAttr);
   assert_status(status == 0, status, "mutex_init");
 }
 
-os::PlatformMonitor::~PlatformMonitor() {
+os::PlatformMonitor::Impl::~Impl() {
   int status = pthread_cond_destroy(&_cond);
   assert_status(status == 0, status, "cond_destroy");
   status = pthread_mutex_destroy(&_mutex);
   assert_status(status == 0, status, "mutex_destroy");
 }
 
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+
+pthread_mutex_t os::PlatformMonitor::_freelist_lock;
+os::PlatformMonitor::Impl* os::PlatformMonitor::_freelist = NULL;
+
+void os::PlatformMonitor::init() {
+  int status = pthread_mutex_init(&_freelist_lock, _mutexAttr);
+  assert_status(status == 0, status, "freelist lock init");
+}
+
+struct os::PlatformMonitor::WithFreeListLocked : public StackObj {
+  WithFreeListLocked() {
+    int status = pthread_mutex_lock(&_freelist_lock);
+    assert_status(status == 0, status, "freelist lock");
+  }
+
+  ~WithFreeListLocked() {
+    int status = pthread_mutex_unlock(&_freelist_lock);
+    assert_status(status == 0, status, "freelist unlock");
+  }
+};
+
+os::PlatformMonitor::PlatformMonitor() {
+  {
+    WithFreeListLocked wfl;
+    _impl = _freelist;
+    if (_impl != NULL) {
+      _freelist = _impl->_next;
+      _impl->_next = NULL;
+      return;
+    }
+  }
+  _impl = new Impl();
+}
+
+os::PlatformMonitor::~PlatformMonitor() {
+  WithFreeListLocked wfl;
+  assert(_impl->_next == NULL, "invariant");
+  _impl->_next = _freelist;
+  _freelist = _impl;
+}
+
+#endif // PLATFORM_MONITOR_IMPL_INDIRECT
+
 // Must already be locked
 int os::PlatformMonitor::wait(jlong millis) {
   assert(millis >= 0, "negative timeout");
@@ -2278,7 +2324,7 @@
     to_abstime(&abst, millis * (NANOUNITS / MILLIUNITS), false, false);
 
     int ret = OS_TIMEOUT;
-    int status = pthread_cond_timedwait(&_cond, &_mutex, &abst);
+    int status = pthread_cond_timedwait(cond(), mutex(), &abst);
     assert_status(status == 0 || status == ETIMEDOUT,
                   status, "cond_timedwait");
     if (status == 0) {
@@ -2286,7 +2332,7 @@
     }
     return ret;
   } else {
-    int status = pthread_cond_wait(&_cond, &_mutex);
+    int status = pthread_cond_wait(cond(), mutex());
     assert_status(status == 0, status, "cond_wait");
     return OS_OK;
   }
--- a/src/hotspot/os/posix/os_posix.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -232,15 +232,60 @@
   PlatformParker();
 };
 
+// Workaround for a bug in macOSX kernel's pthread support (fixed in Mojave?).
+// Avoid ever allocating a pthread_mutex_t at the same address as one of our
+// former pthread_cond_t, by using a freelist of mutex/condvar pairs.
+// Conditional to avoid extra indirection and padding loss on other platforms.
+#ifdef __APPLE__
+#define PLATFORM_MONITOR_IMPL_INDIRECT 1
+#else
+#define PLATFORM_MONITOR_IMPL_INDIRECT 0
+#endif
+
 // Platform specific implementation that underpins VM Monitor/Mutex class
 class PlatformMonitor : public CHeapObj<mtSynchronizer> {
- private:
-  pthread_mutex_t _mutex; // Native mutex for locking
-  pthread_cond_t  _cond;  // Native condition variable for blocking
+  class Impl : public CHeapObj<mtSynchronizer> {
+  public:
+    pthread_mutex_t _mutex;
+    pthread_cond_t _cond;
+    Impl* _next;
+
+    Impl();
+    ~Impl();
+  };
+
+#if PLATFORM_MONITOR_IMPL_INDIRECT
+
+  Impl* _impl;
+
+  pthread_mutex_t* mutex() { return &(_impl->_mutex); }
+  pthread_cond_t* cond() { return &(_impl->_cond); }
+
+  class WithFreeListLocked;
+  static pthread_mutex_t _freelist_lock;
+  static Impl* _freelist;
 
  public:
-  PlatformMonitor();
+  PlatformMonitor();            // Use freelist allocation of impl.
   ~PlatformMonitor();
+
+  static void init();           // Initialize the freelist.
+
+#else
+
+  Impl _impl;
+
+  pthread_mutex_t* mutex() { return &(_impl._mutex); }
+  pthread_cond_t* cond() { return &(_impl._cond); }
+
+ public:
+  static void init() {}         // Nothing needed for the non-indirect case.
+
+  // Default constructor and destructor.
+
+#endif // PLATFORM_MONITOR_IMPL_INDIRECT
+
+ public:
   void lock();
   void unlock();
   bool try_lock();
--- a/src/hotspot/os/posix/os_posix.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -50,28 +50,28 @@
 // Platform Monitor implementation
 
 inline void os::PlatformMonitor::lock() {
-  int status = pthread_mutex_lock(&_mutex);
+  int status = pthread_mutex_lock(mutex());
   assert_status(status == 0, status, "mutex_lock");
 }
 
 inline void os::PlatformMonitor::unlock() {
-  int status = pthread_mutex_unlock(&_mutex);
+  int status = pthread_mutex_unlock(mutex());
   assert_status(status == 0, status, "mutex_unlock");
 }
 
 inline bool os::PlatformMonitor::try_lock() {
-  int status = pthread_mutex_trylock(&_mutex);
+  int status = pthread_mutex_trylock(mutex());
   assert_status(status == 0 || status == EBUSY, status, "mutex_trylock");
   return status == 0;
 }
 
 inline void os::PlatformMonitor::notify() {
-  int status = pthread_cond_signal(&_cond);
+  int status = pthread_cond_signal(cond());
   assert_status(status == 0, status, "cond_signal");
 }
 
 inline void os::PlatformMonitor::notify_all() {
-  int status = pthread_cond_broadcast(&_cond);
+  int status = pthread_cond_broadcast(cond());
   assert_status(status == 0, status, "cond_broadcast");
 }
 
--- a/src/hotspot/os/solaris/os_solaris.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/solaris/os_solaris.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -33,6 +33,7 @@
 #include "compiler/disassembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/filemap.hpp"
 #include "oops/oop.inline.hpp"
@@ -992,6 +993,11 @@
   } else {
     log_warning(os, thread)("Failed to start thread - thr_create failed (%s) for attributes: %s.",
       os::errno_name(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags));
+    // Log some OS information which might explain why creating the thread failed.
+    log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+    LogStream st(Log(os, thread)::info());
+    os::Posix::print_rlimit_info(&st);
+    os::print_memory_info(&st);
   }
 
   if (status != 0) {
--- a/src/hotspot/os/windows/os_windows.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -36,6 +36,7 @@
 #include "compiler/disassembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
+#include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/filemap.hpp"
 #include "oops/oop.inline.hpp"
@@ -669,6 +670,10 @@
   } else {
     log_warning(os, thread)("Failed to start thread - _beginthreadex failed (%s) for attributes: %s.",
       os::errno_name(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag));
+    // Log some OS information which might explain why creating the thread failed.
+    log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
+    LogStream st(Log(os, thread)::info());
+    os::print_memory_info(&st);
   }
 
   if (thread_handle == NULL) {
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zLargePages_linux_x86.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zLargePages.hpp"
-#include "runtime/globals.hpp"
-
-void ZLargePages::initialize_platform() {
-  if (UseLargePages) {
-    if (UseTransparentHugePages) {
-      _state = Transparent;
-    } else {
-      _state = Explicit;
-    }
-  } else {
-    _state = Disabled;
-  }
-}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zNUMA_linux_x86.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2016, 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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "gc/z/zErrno.hpp"
-#include "gc/z/zCPU.hpp"
-#include "gc/z/zNUMA.hpp"
-#include "runtime/os.hpp"
-#include "utilities/debug.hpp"
-
-#include <unistd.h>
-#include <sys/syscall.h>
-
-#ifndef MPOL_F_NODE
-#define MPOL_F_NODE     (1<<0)  // Return next IL mode instead of node mask
-#endif
-
-#ifndef MPOL_F_ADDR
-#define MPOL_F_ADDR     (1<<1)  // Look up VMA using address
-#endif
-
-static int z_get_mempolicy(uint32_t* mode, const unsigned long *nmask, unsigned long maxnode, uintptr_t addr, int flags) {
-  return syscall(__NR_get_mempolicy, mode, nmask, maxnode, addr, flags);
-}
-
-void ZNUMA::initialize_platform() {
-  _enabled = UseNUMA;
-}
-
-uint32_t ZNUMA::count() {
-  if (!_enabled) {
-    // NUMA support not enabled
-    return 1;
-  }
-
-  return os::Linux::numa_max_node() + 1;
-}
-
-uint32_t ZNUMA::id() {
-  if (!_enabled) {
-    // NUMA support not enabled
-    return 0;
-  }
-
-  return os::Linux::get_node_by_cpu(ZCPU::id());
-}
-
-uint32_t ZNUMA::memory_id(uintptr_t addr) {
-  if (!_enabled) {
-    // NUMA support not enabled, assume everything belongs to node zero
-    return 0;
-  }
-
-  uint32_t id = (uint32_t)-1;
-
-  if (z_get_mempolicy(&id, NULL, 0, addr, MPOL_F_NODE | MPOL_F_ADDR) == -1) {
-    ZErrno err;
-    fatal("Failed to get NUMA id for memory at " PTR_FORMAT " (%s)", addr, err.to_string());
-  }
-
-  assert(id < count(), "Invalid NUMA id");
-
-  return id;
-}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -237,8 +237,8 @@
 }
 
 void ZPhysicalMemoryBacking::map(ZPhysicalMemory pmem, uintptr_t offset) const {
-  if (ZUnmapBadViews) {
-    // Only map the good view, for debugging only
+  if (ZVerifyViews) {
+    // Map good view
     map_view(pmem, ZAddress::good(offset), AlwaysPreTouch);
   } else {
     // Map all views
@@ -249,8 +249,8 @@
 }
 
 void ZPhysicalMemoryBacking::unmap(ZPhysicalMemory pmem, uintptr_t offset) const {
-  if (ZUnmapBadViews) {
-    // Only map the good view, for debugging only
+  if (ZVerifyViews) {
+    // Unmap good view
     unmap_view(pmem, ZAddress::good(offset));
   } else {
     // Unmap all views
@@ -260,11 +260,14 @@
   }
 }
 
-void ZPhysicalMemoryBacking::flip(ZPhysicalMemory pmem, uintptr_t offset) const {
-  assert(ZUnmapBadViews, "Should be enabled");
-  const uintptr_t addr_good = ZAddress::good(offset);
-  const uintptr_t addr_bad = ZAddress::is_marked(ZAddressGoodMask) ? ZAddress::remapped(offset) : ZAddress::marked(offset);
-  // Map/Unmap views
-  map_view(pmem, addr_good, false /* pretouch */);
-  unmap_view(pmem, addr_bad);
+void ZPhysicalMemoryBacking::debug_map(ZPhysicalMemory pmem, uintptr_t offset) const {
+  // Map good view
+  assert(ZVerifyViews, "Should be enabled");
+  map_view(pmem, ZAddress::good(offset), false /* pretouch */);
 }
+
+void ZPhysicalMemoryBacking::debug_unmap(ZPhysicalMemory pmem, uintptr_t offset) const {
+  // Unmap good view
+  assert(ZVerifyViews, "Should be enabled");
+  unmap_view(pmem, ZAddress::good(offset));
+}
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/os_cpu/linux_x86/gc/z/zPhysicalMemoryBacking_linux_x86.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -58,7 +58,9 @@
 
   void map(ZPhysicalMemory pmem, uintptr_t offset) const;
   void unmap(ZPhysicalMemory pmem, uintptr_t offset) const;
-  void flip(ZPhysicalMemory pmem, uintptr_t offset) const;
+
+  void debug_map(ZPhysicalMemory pmem, uintptr_t offset) const;
+  void debug_unmap(ZPhysicalMemory pmem, uintptr_t offset) const;
 };
 
 #endif // OS_CPU_LINUX_X86_GC_Z_ZPHYSICALMEMORYBACKING_LINUX_X86_HPP
--- a/src/hotspot/os_cpu/linux_x86/gc/z/zVirtualMemory_linux_x86.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zVirtualMemory.hpp"
-#include "logging/log.hpp"
-
-#include <sys/mman.h>
-#include <sys/types.h>
-
-bool ZVirtualMemoryManager::reserve(uintptr_t start, size_t size) {
-  // Reserve address space
-  const uintptr_t actual_start = (uintptr_t)mmap((void*)start, size, PROT_NONE,
-                                                 MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
-  if (actual_start != start) {
-    log_error(gc)("Failed to reserve address space for Java heap");
-    return false;
-  }
-
-  return true;
-}
--- a/src/hotspot/share/aot/aotCodeHeap.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -931,13 +931,13 @@
 // Scan only klasses_got cells which should have only Klass*,
 // metadata_got cells are scanned only for alive AOT methods
 // by AOTCompiledMethod::metadata_do().
-void AOTCodeHeap::got_metadata_do(void f(Metadata*)) {
+void AOTCodeHeap::got_metadata_do(MetadataClosure* f) {
   for (int i = 1; i < _klasses_got_size; i++) {
     Metadata** p = &_klasses_got[i];
     Metadata* md = *p;
     if (md == NULL)  continue;  // skip non-oops
     if (Metaspace::contains(md)) {
-      f(md);
+      f->do_metadata(md);
     } else {
       intptr_t meta = (intptr_t)md;
       fatal("Invalid value in _klasses_got[%d] = " INTPTR_FORMAT, i, meta);
@@ -969,7 +969,7 @@
 }
 #endif
 
-void AOTCodeHeap::metadata_do(void f(Metadata*)) {
+void AOTCodeHeap::metadata_do(MetadataClosure* f) {
   for (int index = 0; index < _method_count; index++) {
     if (_code_to_aot[index]._state != in_use) {
       continue; // Skip uninitialized entries.
--- a/src/hotspot/share/aot/aotCodeHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/aot/aotCodeHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -252,8 +252,8 @@
 
 
   void oops_do(OopClosure* f);
-  void metadata_do(void f(Metadata*));
-  void got_metadata_do(void f(Metadata*));
+  void metadata_do(MetadataClosure* f);
+  void got_metadata_do(MetadataClosure* f);
 
 #ifdef ASSERT
   bool got_contains(Metadata **p) {
--- a/src/hotspot/share/aot/aotCompiledMethod.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -246,7 +246,7 @@
 
 // Iterate over metadata calling this function.   Used by RedefineClasses
 // Copied from nmethod::metadata_do
-void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
+void AOTCompiledMethod::metadata_do(MetadataClosure* f) {
   address low_boundary = verified_entry_point();
   {
     // Visit all immediate references that are embedded in the instruction stream.
@@ -262,7 +262,7 @@
                "metadata must be found in exactly one place");
         if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
           Metadata* md = r->metadata_value();
-          if (md != _method) f(md);
+          if (md != _method) f->do_metadata(md);
         }
       } else if (iter.type() == relocInfo::virtual_call_type) {
         ResourceMark rm;
@@ -270,13 +270,13 @@
         CompiledIC *ic = CompiledIC_at(&iter);
         if (ic->is_icholder_call()) {
           CompiledICHolder* cichk = ic->cached_icholder();
-          f(cichk->holder_metadata());
-          f(cichk->holder_klass());
+          f->do_metadata(cichk->holder_metadata());
+          f->do_metadata(cichk->holder_klass());
         } else {
           // Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
           Metadata* ic_oop = ic->cached_metadata();
           if (ic_oop != NULL) {
-            f(ic_oop);
+            f->do_metadata(ic_oop);
           }
         }
       } else if (iter.type() == relocInfo::static_call_type ||
@@ -284,7 +284,7 @@
         // Check Method* in AOT c2i stub for other calls.
         Metadata* meta = (Metadata*)nativeLoadGot_at(nativePltCall_at(iter.addr())->plt_c2i_stub())->data();
         if (meta != NULL) {
-          f(meta);
+          f->do_metadata(meta);
         }
       }
     }
@@ -302,11 +302,11 @@
       continue;
     }
     assert(Metaspace::contains(m), "");
-    f(m);
+    f->do_metadata(m);
   }
 
   // Visit metadata not embedded in the other places.
-  if (_method != NULL) f(_method);
+  if (_method != NULL) f->do_metadata(_method);
 }
 
 void AOTCompiledMethod::print() const {
--- a/src/hotspot/share/aot/aotCompiledMethod.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/aot/aotCompiledMethod.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -241,7 +241,7 @@
   address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
   void    set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
 
-  virtual void metadata_do(void f(Metadata*));
+  virtual void metadata_do(MetadataClosure* f);
 
   bool metadata_got_contains(Metadata **p) {
     return p >= &_metadata_got[0] && p < &_metadata_got[_metadata_size];
--- a/src/hotspot/share/aot/aotLoader.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/aot/aotLoader.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -78,7 +78,7 @@
   }
 }
 
-void AOTLoader::metadata_do(void f(Metadata*)) {
+void AOTLoader::metadata_do(MetadataClosure* f) {
   if (UseAOT) {
     FOR_ALL_AOT_HEAPS(heap) {
       (*heap)->metadata_do(f);
--- a/src/hotspot/share/aot/aotLoader.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/aot/aotLoader.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -62,7 +62,7 @@
   static void load_for_klass(InstanceKlass* ik, Thread* thread) NOT_AOT_RETURN;
   static uint64_t get_saved_fingerprint(InstanceKlass* ik) NOT_AOT({ return 0; });
   static void oops_do(OopClosure* f) NOT_AOT_RETURN;
-  static void metadata_do(void f(Metadata*)) NOT_AOT_RETURN;
+  static void metadata_do(MetadataClosure* f) NOT_AOT_RETURN;
   static void mark_evol_dependent_methods(InstanceKlass* dependee) NOT_AOT_RETURN;
 
   NOT_PRODUCT( static void print_statistics() NOT_AOT_RETURN; )
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -53,18 +53,13 @@
 #define PATCHED_ADDR  (max_jint)
 #endif
 
-void PhiResolverState::reset(int max_vregs) {
-  // Initialize array sizes
-  _virtual_operands.at_put_grow(max_vregs - 1, NULL, NULL);
-  _virtual_operands.trunc_to(0);
-  _other_operands.at_put_grow(max_vregs - 1, NULL, NULL);
-  _other_operands.trunc_to(0);
-  _vreg_table.at_put_grow(max_vregs - 1, NULL, NULL);
-  _vreg_table.trunc_to(0);
+void PhiResolverState::reset() {
+  _virtual_operands.clear();
+  _other_operands.clear();
+  _vreg_table.clear();
 }
 
 
-
 //--------------------------------------------------------------
 // PhiResolver
 
@@ -78,13 +73,13 @@
 //  r2 := r3  becomes  r1 := r2
 //  r1 := r2           r2 := r3
 
-PhiResolver::PhiResolver(LIRGenerator* gen, int max_vregs)
+PhiResolver::PhiResolver(LIRGenerator* gen)
  : _gen(gen)
  , _state(gen->resolver_state())
  , _temp(LIR_OprFact::illegalOpr)
 {
   // reinitialize the shared state arrays
-  _state.reset(max_vregs);
+  _state.reset();
 }
 
 
@@ -1021,8 +1016,7 @@
 
     // a block with only one predecessor never has phi functions
     if (sux->number_of_preds() > 1) {
-      int max_phis = cur_state->stack_size() + cur_state->locals_size();
-      PhiResolver resolver(this, _virtual_register_number + max_phis * 2);
+      PhiResolver resolver(this);
 
       ValueStack* sux_state = sux->state();
       Value sux_value;
@@ -3285,7 +3279,14 @@
 
 void LIRGenerator::increment_backedge_counter_conditionally(LIR_Condition cond, LIR_Opr left, LIR_Opr right, CodeEmitInfo* info, int left_bci, int right_bci, int bci) {
   if (compilation()->count_backedges()) {
+#if defined(X86) && !defined(_LP64)
+    // BEWARE! On 32-bit x86 cmp clobbers its left argument so we need a temp copy.
+    LIR_Opr left_copy = new_register(left->type());
+    __ move(left, left_copy);
+    __ cmp(cond, left_copy, right);
+#else
     __ cmp(cond, left, right);
+#endif
     LIR_Opr step = new_register(T_INT);
     LIR_Opr plus_one = LIR_OprFact::intConst(InvocationCounter::count_increment);
     LIR_Opr zero = LIR_OprFact::intConst(0);
--- a/src/hotspot/share/c1/c1_LIRGenerator.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -102,7 +102,7 @@
 
 
 // This is shared state to be used by the PhiResolver so the operand
-// arrays don't have to be reallocated for reach resolution.
+// arrays don't have to be reallocated for each resolution.
 class PhiResolverState: public CompilationResourceObj {
   friend class PhiResolver;
 
@@ -114,7 +114,7 @@
  public:
   PhiResolverState() {}
 
-  void reset(int max_vregs);
+  void reset();
 };
 
 
@@ -146,7 +146,7 @@
   }
 
  public:
-  PhiResolver(LIRGenerator* _lir_gen, int max_vregs);
+  PhiResolver(LIRGenerator* _lir_gen);
   ~PhiResolver();
 
   void move(LIR_Opr src, LIR_Opr dest);
--- a/src/hotspot/share/c1/c1_Runtime1.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1264,7 +1264,7 @@
 
   // If we are patching in a non-perm oop, make sure the nmethod
   // is on the right list.
-  if (ScavengeRootsInCode) {
+  {
     MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag);
     nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
     guarantee(nm != NULL, "only nmethods can contain non-perm oops");
--- a/src/hotspot/share/ci/ciBaseObject.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciBaseObject.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -32,9 +32,8 @@
 //
 // Set the unique identity number of a ciBaseObject.
 void ciBaseObject::set_ident(uint id) {
-  assert((_ident >> FLAG_BITS) == 0, "must only initialize once");
-  assert( id < ((uint)1 << (BitsPerInt-FLAG_BITS)), "id too big");
-  _ident = _ident + (id << FLAG_BITS);
+  assert(_ident == 0, "must only initialize once");
+  _ident = id;
 }
 
 // ------------------------------------------------------------------
@@ -42,7 +41,6 @@
 //
 // Report the unique identity number of a ciBaseObject.
 uint ciBaseObject::ident() {
-  uint id = _ident >> FLAG_BITS;
-  assert(id != 0, "must be initialized");
-  return id;
+  assert(_ident != 0, "must be initialized");
+  return _ident;
 }
--- a/src/hotspot/share/ci/ciBaseObject.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciBaseObject.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -54,10 +54,6 @@
 protected:
   uint     _ident;
 
-  enum { FLAG_BITS   = 1 };
-  enum {
-         SCAVENGABLE_FLAG = 1
-       };
 protected:
   ciBaseObject(): _ident(0) {}
 
--- a/src/hotspot/share/ci/ciEnv.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciEnv.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -465,7 +465,7 @@
   void record_out_of_memory_failure();
 
   // RedefineClasses support
-  void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); }
+  void metadata_do(MetadataClosure* f) { _factory->metadata_do(f); }
 
   // Dump the compilation replay data for the ciEnv to the stream.
   void dump_replay_data(int compile_id);
--- a/src/hotspot/share/ci/ciObject.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciObject.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -59,7 +59,7 @@
     _handle = JNIHandles::make_global(obj);
   }
   _klass = NULL;
-  init_flags_from(o);
+  assert(oopDesc::is_oop_or_null(o), "Checking");
 }
 
 // ------------------------------------------------------------------
@@ -73,7 +73,7 @@
     _handle = JNIHandles::make_global(h);
   }
   _klass = NULL;
-  init_flags_from(h());
+  assert(oopDesc::is_oop_or_null(h()), "Checking");
 }
 
 // ------------------------------------------------------------------
@@ -165,18 +165,10 @@
 // to discourage use of the JNI handle.
 jobject ciObject::constant_encoding() {
   assert(is_null_object() || handle() != NULL, "cannot embed null pointer");
-  assert(can_be_constant(), "oop must be NULL or perm");
   return handle();
 }
 
 // ------------------------------------------------------------------
-// ciObject::can_be_constant
-bool ciObject::can_be_constant() {
-  if (ScavengeRootsInCode >= 1)  return true;  // now everybody can encode as a constant
-  return handle() == NULL;
-}
-
-// ------------------------------------------------------------------
 // ciObject::should_be_constant()
 bool ciObject::should_be_constant() {
   if (ScavengeRootsInCode >= 2)  return true;  // force everybody to be a constant
@@ -193,7 +185,6 @@
     }
   if (klass()->is_subclass_of(env->MethodHandle_klass()) ||
       klass()->is_subclass_of(env->CallSite_klass())) {
-    assert(ScavengeRootsInCode >= 1, "must be");
     // We want to treat these aggressively.
     return true;
   }
@@ -202,18 +193,6 @@
 }
 
 // ------------------------------------------------------------------
-// ciObject::should_be_constant()
-void ciObject::init_flags_from(oop x) {
-  int flags = 0;
-  if (x != NULL) {
-    assert(Universe::heap()->is_in_reserved(x), "must be");
-    if (Universe::heap()->is_scavengable(x))
-      flags |= SCAVENGABLE_FLAG;
-  }
-  _ident |= flags;
-}
-
-// ------------------------------------------------------------------
 // ciObject::print
 //
 // Print debugging output about this ciObject.
@@ -223,9 +202,7 @@
 void ciObject::print(outputStream* st) {
   st->print("<%s", type_string());
   GUARDED_VM_ENTRY(print_impl(st);)
-  st->print(" ident=%d %s address=" INTPTR_FORMAT ">", ident(),
-        is_scavengable() ? "SCAVENGABLE" : "",
-        p2i((address)this));
+  st->print(" ident=%d address=" INTPTR_FORMAT ">", ident(), p2i(this));
 }
 
 // ------------------------------------------------------------------
--- a/src/hotspot/share/ci/ciObject.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciObject.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -68,8 +68,6 @@
   // Get the VM oop that this object holds.
   oop get_oop() const;
 
-  void init_flags_from(oop x);
-
   // Virtual behavior of the print() method.
   virtual void print_impl(outputStream* st) {}
 
@@ -85,22 +83,9 @@
   // A hash value for the convenience of compilers.
   int hash();
 
-  // Tells if this oop has an encoding as a constant.
-  // True if is_perm is true.
-  // Also true if ScavengeRootsInCode is non-zero.
-  // If it does not have an encoding, the compiler is responsible for
-  // making other arrangements for dealing with the oop.
-  // See ciEnv::make_array
-  bool can_be_constant();
-
   // Tells if this oop should be made a constant.
-  // True if is_perm is true or ScavengeRootsInCode > 1.
   bool should_be_constant();
 
-  // Might this object possibly move during a scavenge operation?
-  // If the answer is true and ScavengeRootsInCode==0, the oop cannot be embedded in code.
-  bool is_scavengable() { return (_ident & SCAVENGABLE_FLAG) != 0; }
-
   // The address which the compiler should embed into the
   // generated code to represent this oop.  This address
   // is not the true address of the oop -- it will get patched
--- a/src/hotspot/share/ci/ciObjectFactory.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciObjectFactory.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -689,11 +689,11 @@
 
 // ------------------------------------------------------------------
 // ciObjectFactory::metadata_do
-void ciObjectFactory::metadata_do(void f(Metadata*)) {
+void ciObjectFactory::metadata_do(MetadataClosure* f) {
   if (_ci_metadata == NULL) return;
   for (int j = 0; j< _ci_metadata->length(); j++) {
     Metadata* o = _ci_metadata->at(j)->constant_encoding();
-    f(o);
+    f->do_metadata(o);
   }
 }
 
--- a/src/hotspot/share/ci/ciObjectFactory.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciObjectFactory.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -140,7 +140,7 @@
 
   GrowableArray<ciMetadata*>* get_ci_metadata() const { return _ci_metadata; }
   // RedefineClasses support
-  void metadata_do(void f(Metadata*));
+  void metadata_do(MetadataClosure* f);
 
   void print_contents();
   void print();
--- a/src/hotspot/share/ci/ciUtilities.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciUtilities.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -43,10 +43,9 @@
 
 // ------------------------------------------------------------------
 // card_table_base
-jbyte *ci_card_table_address() {
+CardTable::CardValue* ci_card_table_address() {
   BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust users of this code");
   return ct->byte_map_base();
 }
--- a/src/hotspot/share/ci/ciUtilities.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/ci/ciUtilities.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -26,6 +26,7 @@
 #define SHARE_CI_CIUTILITIES_HPP
 
 #include "ci/ciEnv.hpp"
+#include "gc/shared/cardTable.hpp"
 #include "utilities/globalDefinitions.hpp"
 
 // The following routines and definitions are used internally in the
@@ -50,7 +51,7 @@
 
 const char* basictype_to_str(BasicType t);
 
-jbyte *ci_card_table_address();
+CardTable::CardValue* ci_card_table_address();
 template <typename T> T ci_card_table_address_as() {
   return reinterpret_cast<T>(ci_card_table_address());
 }
--- a/src/hotspot/share/classfile/classFileParser.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -6113,7 +6113,7 @@
           // For the boot and platform class loaders, skip classes that are not found in the
           // java runtime image, such as those found in the --patch-module entries.
           // These classes can't be loaded from the archive during runtime.
-          if (!ClassLoader::is_modules_image(stream->source()) && strncmp(stream->source(), "jrt:", 4) != 0) {
+          if (!stream->from_boot_loader_modules_image() && strncmp(stream->source(), "jrt:", 4) != 0) {
             skip = true;
           }
 
--- a/src/hotspot/share/classfile/classFileStream.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/classFileStream.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,12 +38,14 @@
 ClassFileStream::ClassFileStream(const u1* buffer,
                                  int length,
                                  const char* source,
-                                 bool verify_stream) :
+                                 bool verify_stream,
+                                 bool from_boot_loader_modules_image) :
   _buffer_start(buffer),
   _buffer_end(buffer + length),
   _current(buffer),
   _source(source),
-  _need_verify(verify_stream) {}
+  _need_verify(verify_stream),
+  _from_boot_loader_modules_image(from_boot_loader_modules_image) {}
 
 const u1* ClassFileStream::clone_buffer() const {
   u1* const new_buffer_start = NEW_RESOURCE_ARRAY(u1, length());
@@ -69,7 +71,8 @@
   return new ClassFileStream(new_buffer_start,
                              length(),
                              clone_source(),
-                             need_verify());
+                             need_verify(),
+                             from_boot_loader_modules_image());
 }
 
 uint64_t ClassFileStream::compute_fingerprint() const {
--- a/src/hotspot/share/classfile/classFileStream.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/classFileStream.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -44,7 +44,7 @@
   mutable const u1* _current;    // Current buffer position
   const char* const _source;     // Source of stream (directory name, ZIP/JAR archive name)
   bool _need_verify;             // True if verification is on for the class file
-
+  bool _from_boot_loader_modules_image;  // True if this was created by ClassPathImageEntry.
   void truncated_file_error(TRAPS) const ;
 
  protected:
@@ -57,7 +57,8 @@
   ClassFileStream(const u1* buffer,
                   int length,
                   const char* source,
-                  bool verify_stream = verify); // to be verified by default
+                  bool verify_stream = verify,  // to be verified by default
+                  bool from_boot_loader_modules_image = false);
 
   virtual const ClassFileStream* clone() const;
 
@@ -77,6 +78,7 @@
   const char* source() const { return _source; }
   bool need_verify() const { return _need_verify; }
   void set_verify(bool flag) { _need_verify = flag; }
+  bool from_boot_loader_modules_image() const { return _from_boot_loader_modules_image; }
 
   void check_truncated_file(bool b, TRAPS) const {
     if (b) {
--- a/src/hotspot/share/classfile/classLoader.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/classLoader.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -361,6 +361,8 @@
   }
 }
 
+DEBUG_ONLY(ClassPathImageEntry* ClassPathImageEntry::_singleton = NULL;)
+
 void ClassPathImageEntry::close_jimage() {
   if (_jimage != NULL) {
     (*JImageClose)(_jimage);
@@ -373,12 +375,17 @@
   _jimage(jimage) {
   guarantee(jimage != NULL, "jimage file is null");
   guarantee(name != NULL, "jimage file name is null");
+  assert(_singleton == NULL, "VM supports only one jimage");
+  DEBUG_ONLY(_singleton = this);
   size_t len = strlen(name) + 1;
   _name = NEW_C_HEAP_ARRAY(const char, len, mtClass);
   strncpy((char *)_name, name, len);
 }
 
 ClassPathImageEntry::~ClassPathImageEntry() {
+  assert(_singleton == this, "must be");
+  DEBUG_ONLY(_singleton = NULL);
+
   if (_name != NULL) {
     FREE_C_HEAP_ARRAY(const char, _name);
     _name = NULL;
@@ -442,10 +449,12 @@
     char* data = NEW_RESOURCE_ARRAY(char, size);
     (*JImageGetResource)(_jimage, location, data, size);
     // Resource allocated
+    assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be");
     return new ClassFileStream((u1*)data,
                                (int)size,
                                _name,
-                               ClassFileStream::verify);
+                               ClassFileStream::verify,
+                               true); // from_boot_loader_modules_image
   }
 
   return NULL;
@@ -459,7 +468,9 @@
 }
 
 bool ClassPathImageEntry::is_modules_image() const {
-  return ClassLoader::is_modules_image(name());
+  assert(this == _singleton, "VM supports a single jimage");
+  assert(this == (ClassPathImageEntry*)ClassLoader::get_jrt_entry(), "must be used for jrt entry");
+  return true;
 }
 
 #if INCLUDE_CDS
@@ -737,8 +748,8 @@
         // Check for a jimage
         if (Arguments::has_jimage()) {
           assert(_jrt_entry == NULL, "should not setup bootstrap class search path twice");
+          _jrt_entry = new_entry;
           assert(new_entry != NULL && new_entry->is_modules_image(), "No java runtime image present");
-          _jrt_entry = new_entry;
           assert(_jrt_entry->jimage() != NULL, "No java runtime image");
         }
       } else {
@@ -1499,7 +1510,7 @@
       }
       // for index 0 and the stream->source() is the modules image or has the jrt: protocol.
       // The class must be from the runtime modules image.
-      if (i == 0 && (is_modules_image(src) || string_starts_with(src, "jrt:"))) {
+      if (i == 0 && (stream->from_boot_loader_modules_image() || string_starts_with(src, "jrt:"))) {
         classpath_index = i;
         break;
       }
@@ -1515,7 +1526,7 @@
     // The shared path table is set up after module system initialization.
     // The path table contains no entry before that. Any classes loaded prior
     // to the setup of the shared path table must be from the modules image.
-    assert(is_modules_image(src), "stream must be from modules image");
+    assert(stream->from_boot_loader_modules_image(), "stream must be loaded by boot loader from modules image");
     assert(FileMapInfo::get_number_of_shared_paths() == 0, "shared path table must not have been setup");
     classpath_index = 0;
   }
--- a/src/hotspot/share/classfile/classLoader.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/classLoader.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -114,6 +114,7 @@
 private:
   JImageFile* _jimage;
   const char* _name;
+  DEBUG_ONLY(static ClassPathImageEntry* _singleton;)
 public:
   bool is_modules_image() const;
   bool is_jar_file() const { return false; }
@@ -439,8 +440,6 @@
   // distinguish from a class_name with no package name, as both cases have a NULL return value
   static const char* package_from_name(const char* const class_name, bool* bad_class_name = NULL);
 
-  static bool is_modules_image(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
-
   // Debugging
   static void verify()              PRODUCT_RETURN;
 };
--- a/src/hotspot/share/classfile/javaClasses.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/javaClasses.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -578,7 +578,7 @@
 }
 
 int java_lang_String::utf8_length(oop java_string, typeArrayOop value) {
-  assert(oopDesc::equals(value, java_lang_String::value(java_string)),
+  assert(value_equals(value, java_lang_String::value(java_string)),
          "value must be same as java_lang_String::value(java_string)");
   int length = java_lang_String::length(java_string, value);
   if (length == 0) {
@@ -610,7 +610,7 @@
 }
 
 char* java_lang_String::as_utf8_string(oop java_string, typeArrayOop value, char* buf, int buflen) {
-  assert(oopDesc::equals(value, java_lang_String::value(java_string)),
+  assert(value_equals(value, java_lang_String::value(java_string)),
          "value must be same as java_lang_String::value(java_string)");
   int     length = java_lang_String::length(java_string, value);
   bool is_latin1 = java_lang_String::is_latin1(java_string);
@@ -642,7 +642,7 @@
 }
 
 char* java_lang_String::as_utf8_string(oop java_string, typeArrayOop value, int start, int len, char* buf, int buflen) {
-  assert(oopDesc::equals(value, java_lang_String::value(java_string)),
+  assert(value_equals(value, java_lang_String::value(java_string)),
          "value must be same as java_lang_String::value(java_string)");
   assert(start + len <= java_lang_String::length(java_string), "just checking");
   bool is_latin1 = java_lang_String::is_latin1(java_string);
@@ -686,24 +686,15 @@
   assert(str2->klass() == SystemDictionary::String_klass(),
          "must be java String");
   typeArrayOop value1    = java_lang_String::value_no_keepalive(str1);
-  int          length1   = java_lang_String::length(str1, value1);
   bool         is_latin1 = java_lang_String::is_latin1(str1);
   typeArrayOop value2    = java_lang_String::value_no_keepalive(str2);
-  int          length2   = java_lang_String::length(str2, value2);
   bool         is_latin2 = java_lang_String::is_latin1(str2);
 
-  if ((length1 != length2) || (is_latin1 != is_latin2)) {
-    // Strings of different size or with different
-    // coders are never equal.
+  if (is_latin1 != is_latin2) {
+    // Strings with different coders are never equal.
     return false;
   }
-  int blength1 = value1->length();
-  for (int i = 0; i < blength1; i++) {
-    if (value1->byte_at(i) != value2->byte_at(i)) {
-      return false;
-    }
-  }
-  return true;
+  return value_equals(value1, value2);
 }
 
 void java_lang_String::print(oop java_string, outputStream* st) {
--- a/src/hotspot/share/classfile/javaClasses.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/javaClasses.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -194,6 +194,7 @@
 
   static bool equals(oop java_string, const jchar* chars, int len);
   static bool equals(oop str1, oop str2);
+  static inline bool value_equals(typeArrayOop str_value1, typeArrayOop str_value2);
 
   // Conversion between '.' and '/' formats
   static Handle externalize_classname(Handle java_string, TRAPS) { return char_converter(java_string, '/', '.', THREAD); }
--- a/src/hotspot/share/classfile/javaClasses.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/javaClasses.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -39,31 +39,44 @@
   assert(initialized, "Must be initialized");
   string->obj_field_put_raw(value_offset, buffer);
 }
+
 void java_lang_String::set_value(oop string, typeArrayOop buffer) {
   assert(initialized && (value_offset > 0), "Must be initialized");
   string->obj_field_put(value_offset, (oop)buffer);
 }
+
 void java_lang_String::set_hash(oop string, unsigned int hash) {
   assert(initialized && (hash_offset > 0), "Must be initialized");
   string->int_field_put(hash_offset, hash);
 }
 
 // Accessors
+bool java_lang_String::value_equals(typeArrayOop str_value1, typeArrayOop str_value2) {
+  return (oopDesc::equals(str_value1, str_value2) ||
+          (str_value1->length() == str_value2->length() &&
+           (!memcmp(str_value1->base(T_BYTE),
+                    str_value2->base(T_BYTE),
+                    str_value2->length() * sizeof(jbyte)))));
+}
+
 typeArrayOop java_lang_String::value(oop java_string) {
   assert(initialized && (value_offset > 0), "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
   return (typeArrayOop) java_string->obj_field(value_offset);
 }
+
 typeArrayOop java_lang_String::value_no_keepalive(oop java_string) {
   assert(initialized && (value_offset > 0), "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
   return (typeArrayOop) java_string->obj_field_access<AS_NO_KEEPALIVE>(value_offset);
 }
+
 unsigned int java_lang_String::hash(oop java_string) {
   assert(initialized && (hash_offset > 0), "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
   return java_string->int_field(hash_offset);
 }
+
 bool java_lang_String::is_latin1(oop java_string) {
   assert(initialized && (coder_offset > 0), "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
@@ -71,11 +84,12 @@
   assert(CompactStrings || coder == CODER_UTF16, "Must be UTF16 without CompactStrings");
   return coder == CODER_LATIN1;
 }
+
 int java_lang_String::length(oop java_string, typeArrayOop value) {
   assert(initialized, "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
-  assert(oopDesc::equals(value, java_lang_String::value(java_string)),
-         "value must be same as java_lang_String::value(java_string)");
+  assert(value_equals(value, java_lang_String::value(java_string)),
+         "value must be equal to java_lang_String::value(java_string)");
   if (value == NULL) {
     return 0;
   }
@@ -86,6 +100,7 @@
   }
   return arr_length;
 }
+
 int java_lang_String::length(oop java_string) {
   assert(initialized, "Must be initialized");
   assert(is_instance(java_string), "must be java_string");
@@ -101,42 +116,55 @@
 oop java_lang_ref_Reference::referent(oop ref) {
   return ref->obj_field(referent_offset);
 }
+
 void java_lang_ref_Reference::set_referent(oop ref, oop value) {
   ref->obj_field_put(referent_offset, value);
 }
+
 void java_lang_ref_Reference::set_referent_raw(oop ref, oop value) {
   ref->obj_field_put_raw(referent_offset, value);
 }
+
 HeapWord* java_lang_ref_Reference::referent_addr_raw(oop ref) {
   return ref->obj_field_addr_raw<HeapWord>(referent_offset);
 }
+
 oop java_lang_ref_Reference::next(oop ref) {
   return ref->obj_field(next_offset);
 }
+
 void java_lang_ref_Reference::set_next(oop ref, oop value) {
   ref->obj_field_put(next_offset, value);
 }
+
 void java_lang_ref_Reference::set_next_raw(oop ref, oop value) {
   ref->obj_field_put_raw(next_offset, value);
 }
+
 HeapWord* java_lang_ref_Reference::next_addr_raw(oop ref) {
   return ref->obj_field_addr_raw<HeapWord>(next_offset);
 }
+
 oop java_lang_ref_Reference::discovered(oop ref) {
   return ref->obj_field(discovered_offset);
 }
+
 void java_lang_ref_Reference::set_discovered(oop ref, oop value) {
   ref->obj_field_put(discovered_offset, value);
 }
+
 void java_lang_ref_Reference::set_discovered_raw(oop ref, oop value) {
   ref->obj_field_put_raw(discovered_offset, value);
 }
+
 HeapWord* java_lang_ref_Reference::discovered_addr_raw(oop ref) {
   return ref->obj_field_addr_raw<HeapWord>(discovered_offset);
 }
+
 bool java_lang_ref_Reference::is_final(oop ref) {
   return InstanceKlass::cast(ref->klass())->reference_type() == REF_FINAL;
 }
+
 bool java_lang_ref_Reference::is_phantom(oop ref) {
   return InstanceKlass::cast(ref->klass())->reference_type() == REF_PHANTOM;
 }
--- a/src/hotspot/share/classfile/metadataOnStackMark.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/metadataOnStackMark.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,10 @@
 MetadataOnStackBuffer* MetadataOnStackMark::_current_buffer = NULL;
 NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
 
+class MetadataOnStackClosure : public MetadataClosure {
+  void do_metadata(Metadata* m) { Metadata::mark_on_stack(m); }
+};
+
 // Walk metadata on the stack and mark it so that redefinition doesn't delete
 // it.  Class unloading only deletes in-error class files, methods created by
 // the relocator and dummy constant pools.  None of these appear anywhere except
@@ -55,8 +59,9 @@
   Threads::metadata_handles_do(Metadata::mark_on_stack);
 
   if (redefinition_walk) {
-    Threads::metadata_do(Metadata::mark_on_stack);
-    CodeCache::metadata_do(Metadata::mark_on_stack);
+    MetadataOnStackClosure md_on_stack;
+    Threads::metadata_do(&md_on_stack);
+    CodeCache::metadata_do(&md_on_stack);
     CompileBroker::mark_on_stack();
     JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
     ThreadService::metadata_do(Metadata::mark_on_stack);
--- a/src/hotspot/share/classfile/stackMapFrame.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/stackMapFrame.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,13 +103,16 @@
     case T_ARRAY:
     {
       Symbol* sig = ss.as_symbol(CHECK_(VerificationType::bogus_type()));
-      // Create another symbol to save as signature stream unreferences
-      // this symbol.
-      Symbol* sig_copy =
-        verifier()->create_temporary_symbol(sig, 0, sig->utf8_length(),
-                                 CHECK_(VerificationType::bogus_type()));
-      assert(sig_copy == sig, "symbols don't match");
-      return VerificationType::reference_type(sig_copy);
+      if (!sig->is_permanent()) {
+        // Create another symbol to save as signature stream unreferences
+        // this symbol.
+        Symbol *sig_copy =
+          verifier()->create_temporary_symbol(sig, 0, sig->utf8_length(),
+        CHECK_(VerificationType::bogus_type()));
+        assert(sig_copy == sig, "symbols don't match");
+        sig = sig_copy;
+      }
+      return VerificationType::reference_type(sig);
     }
     case T_INT:     return VerificationType::integer_type();
     case T_BYTE:    return VerificationType::byte_type();
--- a/src/hotspot/share/classfile/symbolTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/symbolTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -487,8 +487,8 @@
   if (sym == NULL) {
     sym = SymbolTable::the_table()->do_add_if_needed(name, len, hash, false, CHECK_NULL);
   }
-  if (sym->refcount() != PERM_REFCOUNT) {
-    sym->increment_refcount();
+  if (!sym->is_permanent()) {
+    sym->make_permanent();
     log_trace_symboltable_helper(sym, "Asked for a permanent symbol, but got a regular one");
   }
   return sym;
--- a/src/hotspot/share/classfile/verifier.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/verifier.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -164,17 +164,15 @@
   // If the class should be verified, first see if we can use the split
   // verifier.  If not, or if verification fails and FailOverToOldVerifier
   // is set, then call the inference verifier.
-
   Symbol* exception_name = NULL;
   const size_t message_buffer_len = klass->name()->utf8_length() + 1024;
-  char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
-  char* exception_message = message_buffer;
+  char* message_buffer = NULL;
+  char* exception_message = NULL;
 
-  const char* klassName = klass->external_name();
   bool can_failover = FailOverToOldVerifier &&
      klass->major_version() < NOFAILOVER_MAJOR_VERSION;
 
-  log_info(class, init)("Start class verification for: %s", klassName);
+  log_info(class, init)("Start class verification for: %s", klass->external_name());
   if (klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
     ClassVerifier split_verifier(klass, THREAD);
     split_verifier.verify_class(THREAD);
@@ -182,8 +180,10 @@
     if (can_failover && !HAS_PENDING_EXCEPTION &&
         (exception_name == vmSymbols::java_lang_VerifyError() ||
          exception_name == vmSymbols::java_lang_ClassFormatError())) {
-      log_info(verification)("Fail over class verification to old verifier for: %s", klassName);
-      log_info(class, init)("Fail over class verification to old verifier for: %s", klassName);
+      log_info(verification)("Fail over class verification to old verifier for: %s", klass->external_name());
+      log_info(class, init)("Fail over class verification to old verifier for: %s", klass->external_name());
+      message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
+      exception_message = message_buffer;
       exception_name = inference_verify(
         klass, message_buffer, message_buffer_len, THREAD);
     }
@@ -191,6 +191,8 @@
       exception_message = split_verifier.exception_message();
     }
   } else {
+    message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
+    exception_message = message_buffer;
     exception_name = inference_verify(
         klass, message_buffer, message_buffer_len, THREAD);
   }
@@ -198,20 +200,19 @@
   LogTarget(Info, class, init) lt1;
   if (lt1.is_enabled()) {
     LogStream ls(lt1);
-    log_end_verification(&ls, klassName, exception_name, THREAD);
+    log_end_verification(&ls, klass->external_name(), exception_name, THREAD);
   }
   LogTarget(Info, verification) lt2;
   if (lt2.is_enabled()) {
     LogStream ls(lt2);
-    log_end_verification(&ls, klassName, exception_name, THREAD);
+    log_end_verification(&ls, klass->external_name(), exception_name, THREAD);
   }
 
   if (HAS_PENDING_EXCEPTION) {
     return false; // use the existing exception
   } else if (exception_name == NULL) {
-    return true; // verifcation succeeded
+    return true; // verification succeeded
   } else { // VerifyError or ClassFormatError to be created and thrown
-    ResourceMark rm(THREAD);
     Klass* kls =
       SystemDictionary::resolve_or_fail(exception_name, true, CHECK_false);
     if (log_is_enabled(Debug, class, resolve)) {
@@ -228,7 +229,10 @@
       }
       kls = kls->super();
     }
-    message_buffer[message_buffer_len - 1] = '\0'; // just to be sure
+    if (message_buffer != NULL) {
+      message_buffer[message_buffer_len - 1] = '\0'; // just to be sure
+    }
+    assert(exception_message != NULL, "");
     THROW_MSG_(exception_name, exception_message, false);
   }
 }
@@ -569,17 +573,18 @@
 
 ClassVerifier::ClassVerifier(
     InstanceKlass* klass, TRAPS)
-    : _thread(THREAD), _exception_type(NULL), _message(NULL), _klass(klass) {
+    : _thread(THREAD), _previous_symbol(NULL), _symbols(NULL), _exception_type(NULL),
+      _message(NULL), _klass(klass) {
   _this_type = VerificationType::reference_type(klass->name());
-  // Create list to hold symbols in reference area.
-  _symbols = new GrowableArray<Symbol*>(100, 0, NULL);
 }
 
 ClassVerifier::~ClassVerifier() {
   // Decrement the reference count for any symbols created.
-  for (int i = 0; i < _symbols->length(); i++) {
-    Symbol* s = _symbols->at(i);
-    s->decrement_refcount();
+  if (_symbols != NULL) {
+    for (int i = 0; i < _symbols->length(); i++) {
+      Symbol* s = _symbols->at(i);
+      s->decrement_refcount();
+    }
   }
 }
 
@@ -632,10 +637,9 @@
   int32_t max_locals = m->max_locals();
   constantPoolHandle cp(THREAD, m->constants());
 
-  if (!SignatureVerifier::is_valid_method_signature(m->signature())) {
-    class_format_error("Invalid method signature");
-    return;
-  }
+  // Method signature was checked in ClassFileParser.
+  assert(SignatureVerifier::is_valid_method_signature(m->signature()),
+         "Invalid method signature");
 
   // Initial stack map frame: offset is 0, stack is initially empty.
   StackMapFrame current_frame(max_locals, max_stack, this);
@@ -2110,12 +2114,9 @@
         vmSymbols::java_lang_invoke_MethodType()), CHECK_VERIFY(this));
   } else if (tag.is_dynamic_constant()) {
     Symbol* constant_type = cp->uncached_signature_ref_at(index);
-    if (!SignatureVerifier::is_valid_type_signature(constant_type)) {
-      class_format_error(
-        "Invalid type for dynamic constant in class %s referenced "
-        "from constant pool index %d", _klass->external_name(), index);
-      return;
-    }
+    // Field signature was checked in ClassFileParser.
+    assert(SignatureVerifier::is_valid_type_signature(constant_type),
+           "Invalid type for dynamic constant");
     assert(sizeof(VerificationType) == sizeof(uintptr_t),
           "buffer type must match VerificationType size");
     uintptr_t constant_type_buffer[2];
@@ -2235,12 +2236,9 @@
   Symbol* field_name = cp->name_ref_at(index);
   Symbol* field_sig = cp->signature_ref_at(index);
 
-  if (!SignatureVerifier::is_valid_type_signature(field_sig)) {
-    class_format_error(
-      "Invalid signature for field in class %s referenced "
-      "from constant pool index %d", _klass->external_name(), index);
-    return;
-  }
+  // Field signature was checked in ClassFileParser.
+  assert(SignatureVerifier::is_valid_type_signature(field_sig),
+         "Invalid field signature");
 
   // Get referenced class type
   VerificationType ref_class_type = cp_ref_index_to_type(
@@ -2719,12 +2717,9 @@
   Symbol* method_name = cp->name_ref_at(index);
   Symbol* method_sig = cp->signature_ref_at(index);
 
-  if (!SignatureVerifier::is_valid_method_signature(method_sig)) {
-    class_format_error(
-      "Invalid method signature in class %s referenced "
-      "from constant pool index %d", _klass->external_name(), index);
-    return;
-  }
+  // Method signature was checked in ClassFileParser.
+  assert(SignatureVerifier::is_valid_method_signature(method_sig),
+         "Invalid method signature");
 
   // Get referenced class type
   VerificationType ref_class_type;
@@ -3102,13 +3097,23 @@
 // they can be reference counted.
 Symbol* ClassVerifier::create_temporary_symbol(const Symbol *s, int begin,
                                                int end, TRAPS) {
-  Symbol* sym = SymbolTable::new_symbol(s, begin, end, CHECK_NULL);
-  _symbols->push(sym);
-  return sym;
+  const char* name = (const char*)s->base() + begin;
+  int length = end - begin;
+  return create_temporary_symbol(name, length, CHECK_NULL);
 }
 
-Symbol* ClassVerifier::create_temporary_symbol(const char *s, int length, TRAPS) {
-  Symbol* sym = SymbolTable::new_symbol(s, length, CHECK_NULL);
-  _symbols->push(sym);
+Symbol* ClassVerifier::create_temporary_symbol(const char *name, int length, TRAPS) {
+  // Quick deduplication check
+  if (_previous_symbol != NULL && _previous_symbol->equals(name, length)) {
+    return _previous_symbol;
+  }
+  Symbol* sym = SymbolTable::new_symbol(name, length, CHECK_NULL);
+  if (!sym->is_permanent()) {
+    if (_symbols == NULL) {
+      _symbols = new GrowableArray<Symbol*>(50, 0, NULL);
+    }
+    _symbols->push(sym);
+  }
+  _previous_symbol = sym;
   return sym;
 }
--- a/src/hotspot/share/classfile/verifier.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/classfile/verifier.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -250,6 +250,8 @@
 class ClassVerifier : public StackObj {
  private:
   Thread* _thread;
+
+  Symbol* _previous_symbol;          // cache of the previously looked up symbol
   GrowableArray<Symbol*>* _symbols;  // keep a list of symbols created
 
   Symbol* _exception_type;
@@ -411,12 +413,18 @@
   // created, we can't use a TempNewSymbol.
   Symbol* create_temporary_symbol(const Symbol* s, int begin, int end, TRAPS);
   Symbol* create_temporary_symbol(const char *s, int length, TRAPS);
-
   Symbol* create_temporary_symbol(Symbol* s) {
-    // This version just updates the reference count and saves the symbol to be
-    // dereferenced later.
-    s->increment_refcount();
-    _symbols->push(s);
+    if (s == _previous_symbol) {
+      return s;
+    }
+    if (!s->is_permanent()) {
+      s->increment_refcount();
+      if (_symbols == NULL) {
+        _symbols = new GrowableArray<Symbol*>(50, 0, NULL);
+      }
+      _symbols->push(s);
+    }
+    _previous_symbol = s;
     return s;
   }
 
--- a/src/hotspot/share/code/codeCache.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/code/codeCache.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -145,7 +145,6 @@
 address CodeCache::_low_bound = 0;
 address CodeCache::_high_bound = 0;
 int CodeCache::_number_of_nmethods_with_dependencies = 0;
-nmethod* CodeCache::_scavenge_root_nmethods = NULL;
 ExceptionCache* volatile CodeCache::_exception_cache_purge_list = NULL;
 
 // Initialize arrays of CodeHeap subsets
@@ -668,7 +667,7 @@
   }
 }
 
-void CodeCache::metadata_do(void f(Metadata* m)) {
+void CodeCache::metadata_do(MetadataClosure* f) {
   assert_locked_or_safepoint(CodeCache_lock);
   NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
   while(iter.next()) {
@@ -711,167 +710,6 @@
   }
 }
 
-// Walk the list of methods which might contain oops to the java heap.
-void CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure* f) {
-  assert_locked_or_safepoint(CodeCache_lock);
-
-  const bool fix_relocations = f->fix_relocations();
-  debug_only(mark_scavenge_root_nmethods());
-
-  nmethod* prev = NULL;
-  nmethod* cur = scavenge_root_nmethods();
-  while (cur != NULL) {
-    debug_only(cur->clear_scavenge_root_marked());
-    assert(cur->scavenge_root_not_marked(), "");
-    assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
-
-    bool is_live = (!cur->is_zombie() && !cur->is_unloaded());
-    LogTarget(Trace, gc, nmethod) lt;
-    if (lt.is_enabled()) {
-      LogStream ls(lt);
-      CompileTask::print(&ls, cur,
-        is_live ? "scavenge root " : "dead scavenge root", /*short_form:*/ true);
-    }
-    if (is_live) {
-      // Perform cur->oops_do(f), maybe just once per nmethod.
-      f->do_code_blob(cur);
-    }
-    nmethod* const next = cur->scavenge_root_link();
-    // The scavengable nmethod list must contain all methods with scavengable
-    // oops. It is safe to include more nmethod on the list, but we do not
-    // expect any live non-scavengable nmethods on the list.
-    if (fix_relocations) {
-      if (!is_live || !cur->detect_scavenge_root_oops()) {
-        unlink_scavenge_root_nmethod(cur, prev);
-      } else {
-        prev = cur;
-      }
-    }
-    cur = next;
-  }
-
-  // Check for stray marks.
-  debug_only(verify_perm_nmethods(NULL));
-}
-
-void CodeCache::register_scavenge_root_nmethod(nmethod* nm) {
-  assert_locked_or_safepoint(CodeCache_lock);
-  if (!nm->on_scavenge_root_list() && nm->detect_scavenge_root_oops()) {
-    add_scavenge_root_nmethod(nm);
-  }
-}
-
-void CodeCache::verify_scavenge_root_nmethod(nmethod* nm) {
-  nm->verify_scavenge_root_oops();
-}
-
-void CodeCache::add_scavenge_root_nmethod(nmethod* nm) {
-  assert_locked_or_safepoint(CodeCache_lock);
-
-  nm->set_on_scavenge_root_list();
-  nm->set_scavenge_root_link(_scavenge_root_nmethods);
-  set_scavenge_root_nmethods(nm);
-  print_trace("add_scavenge_root", nm);
-}
-
-void CodeCache::unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev) {
-  assert_locked_or_safepoint(CodeCache_lock);
-
-  assert((prev == NULL && scavenge_root_nmethods() == nm) ||
-         (prev != NULL && prev->scavenge_root_link() == nm), "precondition");
-
-  print_trace("unlink_scavenge_root", nm);
-  if (prev == NULL) {
-    set_scavenge_root_nmethods(nm->scavenge_root_link());
-  } else {
-    prev->set_scavenge_root_link(nm->scavenge_root_link());
-  }
-  nm->set_scavenge_root_link(NULL);
-  nm->clear_on_scavenge_root_list();
-}
-
-void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) {
-  assert_locked_or_safepoint(CodeCache_lock);
-
-  print_trace("drop_scavenge_root", nm);
-  nmethod* prev = NULL;
-  for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
-    if (cur == nm) {
-      unlink_scavenge_root_nmethod(cur, prev);
-      return;
-    }
-    prev = cur;
-  }
-  assert(false, "should have been on list");
-}
-
-void CodeCache::prune_scavenge_root_nmethods() {
-  assert_locked_or_safepoint(CodeCache_lock);
-
-  debug_only(mark_scavenge_root_nmethods());
-
-  nmethod* last = NULL;
-  nmethod* cur = scavenge_root_nmethods();
-  while (cur != NULL) {
-    nmethod* next = cur->scavenge_root_link();
-    debug_only(cur->clear_scavenge_root_marked());
-    assert(cur->scavenge_root_not_marked(), "");
-    assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
-
-    if (!cur->is_zombie() && !cur->is_unloaded()
-        && cur->detect_scavenge_root_oops()) {
-      // Keep it.  Advance 'last' to prevent deletion.
-      last = cur;
-    } else {
-      // Prune it from the list, so we don't have to look at it any more.
-      print_trace("prune_scavenge_root", cur);
-      unlink_scavenge_root_nmethod(cur, last);
-    }
-    cur = next;
-  }
-
-  // Check for stray marks.
-  debug_only(verify_perm_nmethods(NULL));
-}
-
-#ifndef PRODUCT
-void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) {
-  // While we are here, verify the integrity of the list.
-  mark_scavenge_root_nmethods();
-  for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
-    assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
-    cur->clear_scavenge_root_marked();
-  }
-  verify_perm_nmethods(f);
-}
-
-// Temporarily mark nmethods that are claimed to be on the scavenge list.
-void CodeCache::mark_scavenge_root_nmethods() {
-  NMethodIterator iter(NMethodIterator::only_alive);
-  while(iter.next()) {
-    nmethod* nm = iter.method();
-    assert(nm->scavenge_root_not_marked(), "clean state");
-    if (nm->on_scavenge_root_list())
-      nm->set_scavenge_root_marked();
-  }
-}
-
-// If the closure is given, run it on the unlisted nmethods.
-// Also make sure that the effects of mark_scavenge_root_nmethods is gone.
-void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) {
-  NMethodIterator iter(NMethodIterator::only_alive);
-  while(iter.next()) {
-    nmethod* nm = iter.method();
-    bool call_f = (f_or_null != NULL);
-    assert(nm->scavenge_root_not_marked(), "must be already processed");
-    if (nm->on_scavenge_root_list())
-      call_f = false;  // don't show this one to the client
-    Universe::heap()->verify_nmethod(nm);
-    if (call_f)  f_or_null->do_code_blob(nm);
-  }
-}
-#endif //PRODUCT
-
 void CodeCache::verify_clean_inline_caches() {
 #ifdef ASSERT
   NMethodIterator iter(NMethodIterator::only_alive_and_not_unloading);
@@ -929,12 +767,6 @@
   _exception_cache_purge_list = NULL;
 }
 
-void CodeCache::gc_prologue() { }
-
-void CodeCache::gc_epilogue() {
-  prune_scavenge_root_nmethods();
-}
-
 uint8_t CodeCache::_unloading_cycle = 1;
 
 void CodeCache::increment_unloading_cycle() {
@@ -1229,13 +1061,14 @@
       // ...Already marked in the previous pass; count it here.
       // Also counts AOT compiled methods, already marked.
       number_of_marked_CodeBlobs++;
-    } else if (nm->is_evol_dependent()) {
+    } else if (nm->has_evol_metadata()) {
       ResourceMark rm;
       nm->mark_for_deoptimization();
       number_of_marked_CodeBlobs++;
-    } else  {
-      // flush caches in case they refer to a redefined Method*
-      nm->clear_inline_caches();
+    } else {
+      // Inline caches that refer to an nmethod are deoptimized already, because
+      // the Method* is walked in the metadata section of the nmethod.
+      assert(!nm->is_evol_dependent(), "should no longer be necessary");
     }
   }
 
--- a/src/hotspot/share/code/codeCache.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/code/codeCache.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -94,14 +94,10 @@
   static address _low_bound;                            // Lower bound of CodeHeap addresses
   static address _high_bound;                           // Upper bound of CodeHeap addresses
   static int _number_of_nmethods_with_dependencies;     // Total number of nmethods with dependencies
-  static nmethod* _scavenge_root_nmethods;              // linked via nm->scavenge_root_link()
   static uint8_t _unloading_cycle;                      // Global state for recognizing old nmethods that need to be unloaded
 
   static ExceptionCache* volatile _exception_cache_purge_list;
 
-  static void mark_scavenge_root_nmethods() PRODUCT_RETURN;
-  static void verify_perm_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN;
-
   // CodeHeap management
   static void initialize_heaps();                             // Initializes the CodeHeaps
   // Check the code heap sizes set by the user via command line
@@ -124,10 +120,6 @@
   static int    allocated_segments();
   static size_t freelists_length();
 
-  static void set_scavenge_root_nmethods(nmethod* nm) { _scavenge_root_nmethods = nm; }
-  static void prune_scavenge_root_nmethods();
-  static void unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev);
-
   // Make private to prevent unsafe calls.  Not all CodeBlob*'s are embedded in a CodeHeap.
   static bool contains(CodeBlob *p) { fatal("don't call me!"); return false; }
 
@@ -155,7 +147,7 @@
   static void blobs_do(void f(CodeBlob* cb));              // iterates over all CodeBlobs
   static void blobs_do(CodeBlobClosure* f);                // iterates over all CodeBlobs
   static void nmethods_do(void f(nmethod* nm));            // iterates over all nmethods
-  static void metadata_do(void f(Metadata* m));            // iterates over metadata in alive nmethods
+  static void metadata_do(MetadataClosure* f);             // iterates over metadata in alive nmethods
 
   // Lookup
   static CodeBlob* find_blob(void* start);              // Returns the CodeBlob containing the given address
@@ -171,8 +163,6 @@
   static int       nmethod_count(int code_blob_type);
 
   // GC support
-  static void gc_epilogue();
-  static void gc_prologue();
   static void verify_oops();
   // If any oops are not marked this method unloads (i.e., breaks root links
   // to) any unmarked codeBlobs in the cache.  Sets "marked_for_unloading"
@@ -189,25 +179,9 @@
   static void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
   static uint8_t unloading_cycle() { return _unloading_cycle; }
   static void increment_unloading_cycle();
-  static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN;
   static void release_exception_cache(ExceptionCache* entry);
   static void purge_exception_caches();
 
-  // Apply f to every live code blob in scavengable nmethods. Prune nmethods
-  // from the list of scavengable nmethods if f->fix_relocations() and a nmethod
-  // no longer has scavengable oops.  If f->fix_relocations(), then f must copy
-  // objects to their new location immediately to avoid fixing nmethods on the
-  // basis of the old object locations.
-  static void scavenge_root_nmethods_do(CodeBlobToOopClosure* f);
-
-  static nmethod* scavenge_root_nmethods()            { return _scavenge_root_nmethods; }
-  // register_scavenge_root_nmethod() conditionally adds the nmethod to the list
-  // if it is not already on the list and has a scavengeable root
-  static void register_scavenge_root_nmethod(nmethod* nm);
-  static void verify_scavenge_root_nmethod(nmethod* nm);
-  static void add_scavenge_root_nmethod(nmethod* nm);
-  static void drop_scavenge_root_nmethod(nmethod* nm);
-
   // Printing/debugging
   static void print();                           // prints summary
   static void print_internals();
--- a/src/hotspot/share/code/compiledMethod.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/code/compiledMethod.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -415,20 +415,22 @@
 
 #ifdef ASSERT
 // Check class_loader is alive for this bit of metadata.
-static void check_class(Metadata* md) {
-   Klass* klass = NULL;
-   if (md->is_klass()) {
-     klass = ((Klass*)md);
-   } else if (md->is_method()) {
-     klass = ((Method*)md)->method_holder();
-   } else if (md->is_methodData()) {
-     klass = ((MethodData*)md)->method()->method_holder();
-   } else {
-     md->print();
-     ShouldNotReachHere();
-   }
-   assert(klass->is_loader_alive(), "must be alive");
-}
+class CheckClass : public MetadataClosure {
+  void do_metadata(Metadata* md) {
+    Klass* klass = NULL;
+    if (md->is_klass()) {
+      klass = ((Klass*)md);
+    } else if (md->is_method()) {
+      klass = ((Method*)md)->method_holder();
+    } else if (md->is_methodData()) {
+      klass = ((MethodData*)md)->method()->method_holder();
+    } else {
+      md->print();
+      ShouldNotReachHere();
+    }
+    assert(klass->is_loader_alive(), "must be alive");
+  }
+};
 #endif // ASSERT
 
 
@@ -550,8 +552,11 @@
   // All static stubs need to be cleaned.
   clean_ic_stubs();
 
+#ifdef ASSERT
   // Check that the metadata embedded in the nmethod is alive
-  DEBUG_ONLY(metadata_do(check_class));
+  CheckClass check_class;
+  metadata_do(&check_class);
+#endif
   return true;
 }
 
@@ -628,3 +633,35 @@
          os::is_readable_pointer(method->constants()) &&
          os::is_readable_pointer(method->signature());
 }
+
+class HasEvolDependency : public MetadataClosure {
+  bool _has_evol_dependency;
+ public:
+  HasEvolDependency() : _has_evol_dependency(false) {}
+  void do_metadata(Metadata* md) {
+    if (md->is_method()) {
+      Method* method = (Method*)md;
+      if (method->is_old()) {
+        _has_evol_dependency = true;
+      }
+    }
+  }
+  bool has_evol_dependency() const { return _has_evol_dependency; }
+};
+
+bool CompiledMethod::has_evol_metadata() {
+  // Check the metadata in relocIter and CompiledIC and also deoptimize
+  // any nmethod that has reference to old methods.
+  HasEvolDependency check_evol;
+  metadata_do(&check_evol);
+  if (check_evol.has_evol_dependency() && log_is_enabled(Debug, redefine, class, nmethod)) {
+    ResourceMark rm;
+    log_debug(redefine, class, nmethod)
+            ("Found evol dependency of nmethod %s.%s(%s) compile_id=%d on in nmethod metadata",
+             _method->method_holder()->external_name(),
+             _method->name()->as_C_string(),
+             _method->signature()->as_C_string(),
+             compile_id());
+  }
+  return check_evol.has_evol_dependency();
+}
--- a/src/hotspot/share/code/compiledMethod.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/code/compiledMethod.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -38,6 +38,7 @@
 class NativeCallWrapper;
 class ScopeDesc;
 class CompiledIC;
+class MetadataClosure;
 
 // This class is used internally by nmethods, to cache
 // exception/pc/handler information.
@@ -368,6 +369,8 @@
   void verify_oop_relocations();
 
   virtual bool is_evol_dependent() = 0;
+  bool has_evol_metadata();
+
   // Fast breakpoint support. Tells if this compiled method is
   // dependent on the given method. Returns true if this nmethod
   // corresponds to the given method as well.
@@ -384,7 +387,7 @@
   Method* attached_method(address call_pc);
   Method* attached_method_before_pc(address pc);
 
-  virtual void metadata_do(void f(Metadata*)) = 0;
+  virtual void metadata_do(MetadataClosure* f) = 0;
 
   // GC support
  protected:
@@ -408,10 +411,6 @@
   PcDesc* find_pc_desc(address pc, bool approximate) {
     return _pc_desc_container.find_pc_desc(pc, approximate, PcDescSearch(code_begin(), scopes_pcs_begin(), scopes_pcs_end()));
   }
-
-protected:
-  // Used by some GCs to chain nmethods.
-  nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods
 };
 
 #endif // SHARE_CODE_COMPILEDMETHOD_HPP
--- a/src/hotspot/share/code/nmethod.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/code/nmethod.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -423,8 +423,6 @@
   _oops_do_mark_link       = NULL;
   _jmethod_id              = NULL;
   _osr_link                = NULL;
-  _scavenge_root_link      = NULL;
-  _scavenge_root_state     = 0;
 #if INCLUDE_RTM_OPT
   _rtm_state               = NoRTM;
 #endif
@@ -611,10 +609,10 @@
     code_buffer->copy_values_to(this);
 
     clear_unloading_state();
-    if (ScavengeRootsInCode) {
-      Universe::heap()->register_nmethod(this);
-    }
+
+    Universe::heap()->register_nmethod(this);
     debug_only(Universe::heap()->verify_nmethod(this));
+
     CodeCache::commit(this);
   }
 
@@ -771,9 +769,8 @@
     debug_info->copy_to(this);
     dependencies->copy_to(this);
     clear_unloading_state();
-    if (ScavengeRootsInCode) {
-      Universe::heap()->register_nmethod(this);
-    }
+
+    Universe::heap()->register_nmethod(this);
     debug_only(Universe::heap()->verify_nmethod(this));
 
     CodeCache::commit(this);
@@ -1361,10 +1358,6 @@
     ec = next;
   }
 
-  if (on_scavenge_root_list()) {
-    CodeCache::drop_scavenge_root_nmethod(this);
-  }
-
 #if INCLUDE_JVMCI
   assert(_jvmci_installed_code == NULL, "should have been nulled out when transitioned to zombie");
   assert(_speculation_log == NULL, "should have been nulled out when transitioned to zombie");
@@ -1506,7 +1499,7 @@
 }
 
 // Iterate over metadata calling this function.   Used by RedefineClasses
-void nmethod::metadata_do(void f(Metadata*)) {
+void nmethod::metadata_do(MetadataClosure* f) {
   {
     // Visit all immediate references that are embedded in the instruction stream.
     RelocIterator iter(this, oops_reloc_begin());
@@ -1521,7 +1514,7 @@
                "metadata must be found in exactly one place");
         if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
           Metadata* md = r->metadata_value();
-          if (md != _method) f(md);
+          if (md != _method) f->do_metadata(md);
         }
       } else if (iter.type() == relocInfo::virtual_call_type) {
         // Check compiledIC holders associated with this nmethod
@@ -1529,12 +1522,12 @@
         CompiledIC *ic = CompiledIC_at(&iter);
         if (ic->is_icholder_call()) {
           CompiledICHolder* cichk = ic->cached_icholder();
-          f(cichk->holder_metadata());
-          f(cichk->holder_klass());
+          f->do_metadata(cichk->holder_metadata());
+          f->do_metadata(cichk->holder_klass());
         } else {
           Metadata* ic_oop = ic->cached_metadata();
           if (ic_oop != NULL) {
-            f(ic_oop);
+            f->do_metadata(ic_oop);
           }
         }
       }
@@ -1545,11 +1538,11 @@
   for (Metadata** p = metadata_begin(); p < metadata_end(); p++) {
     if (*p == Universe::non_oop_word() || *p == NULL)  continue;  // skip non-oops
     Metadata* md = *p;
-    f(md);
+    f->do_metadata(md);
   }
 
   // Visit metadata not embedded in the other places.
-  if (_method != NULL) f(_method);
+  if (_method != NULL) f->do_metadata(_method);
 }
 
 // The _is_unloading_state encodes a tuple comprising the unloading cycle
@@ -1778,44 +1771,6 @@
   log_trace(gc, nmethod)("oops_do_marking_epilogue");
 }
 
-class DetectScavengeRoot: public OopClosure {
-  bool     _detected_scavenge_root;
-  nmethod* _print_nm;
-public:
-  DetectScavengeRoot(nmethod* nm) : _detected_scavenge_root(false), _print_nm(nm) {}
-
-  bool detected_scavenge_root() { return _detected_scavenge_root; }
-  virtual void do_oop(oop* p) {
-    if ((*p) != NULL && Universe::heap()->is_scavengable(*p)) {
-      NOT_PRODUCT(maybe_print(p));
-      _detected_scavenge_root = true;
-    }
-  }
-  virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
-
-#ifndef PRODUCT
-  void maybe_print(oop* p) {
-    LogTarget(Trace, gc, nmethod) lt;
-    if (lt.is_enabled()) {
-      LogStream ls(lt);
-      if (!_detected_scavenge_root) {
-        CompileTask::print(&ls, _print_nm, "new scavenge root", /*short_form:*/ true);
-      }
-      ls.print("" PTR_FORMAT "[offset=%d] detected scavengable oop " PTR_FORMAT " (found at " PTR_FORMAT ") ",
-               p2i(_print_nm), (int)((intptr_t)p - (intptr_t)_print_nm),
-               p2i(*p), p2i(p));
-      ls.cr();
-    }
-  }
-#endif //PRODUCT
-};
-
-bool nmethod::detect_scavenge_root_oops() {
-  DetectScavengeRoot detect_scavenge_root(this);
-  oops_do(&detect_scavenge_root);
-  return detect_scavenge_root.detected_scavenge_root();
-}
-
 inline bool includes(void* p, void* from, void* to) {
   return from <= p && p < to;
 }
@@ -2267,41 +2222,6 @@
 
 
 // -----------------------------------------------------------------------------
-// Non-product code
-#ifndef PRODUCT
-
-class DebugScavengeRoot: public OopClosure {
-  nmethod* _nm;
-  bool     _ok;
-public:
-  DebugScavengeRoot(nmethod* nm) : _nm(nm), _ok(true) { }
-  bool ok() { return _ok; }
-  virtual void do_oop(oop* p) {
-    if ((*p) == NULL || !Universe::heap()->is_scavengable(*p))  return;
-    if (_ok) {
-      _nm->print_nmethod(true);
-      _ok = false;
-    }
-    tty->print_cr("*** scavengable oop " PTR_FORMAT " found at " PTR_FORMAT " (offset %d)",
-                  p2i(*p), p2i(p), (int)((intptr_t)p - (intptr_t)_nm));
-    (*p)->print();
-  }
-  virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
-};
-
-void nmethod::verify_scavenge_root_oops() {
-  if (!on_scavenge_root_list()) {
-    // Actually look inside, to verify the claim that it's clean.
-    DebugScavengeRoot debug_scavenge_root(this);
-    oops_do(&debug_scavenge_root);
-    if (!debug_scavenge_root.ok())
-      fatal("found an unadvertised bad scavengable oop in the code cache");
-  }
-  assert(scavenge_root_not_marked(), "");
-}
-
-#endif // PRODUCT
-
 // Printing operations
 
 void nmethod::print() const {
@@ -2327,7 +2247,6 @@
     tty->print(" for method " INTPTR_FORMAT , p2i(method()));
     tty->print(" { ");
     tty->print_cr("%s ", state());
-    if (on_scavenge_root_list())  tty->print("scavenge_root ");
     tty->print_cr("}:");
   }
   if (size              () > 0) tty->print_cr(" total in heap  [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
--- a/src/hotspot/share/code/nmethod.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/code/nmethod.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -131,8 +131,6 @@
   bool _oops_are_stale;  // indicates that it's no longer safe to access oops section
 #endif
 
-  jbyte _scavenge_root_state;
-
 #if INCLUDE_RTM_OPT
   // RTM state at compile time. Used during deoptimization to decide
   // whether to restart collecting RTM locking abort statistic again.
@@ -410,24 +408,6 @@
   void fix_oop_relocations(address begin, address end) { fix_oop_relocations(begin, end, false); }
   void fix_oop_relocations()                           { fix_oop_relocations(NULL, NULL, false); }
 
-  // Scavengable oop support
-  bool  on_scavenge_root_list() const                  { return (_scavenge_root_state & 1) != 0; }
- protected:
-  enum { sl_on_list = 0x01, sl_marked = 0x10 };
-  void  set_on_scavenge_root_list()                    { _scavenge_root_state = sl_on_list; }
-  void  clear_on_scavenge_root_list()                  { _scavenge_root_state = 0; }
-  // assertion-checking and pruning logic uses the bits of _scavenge_root_state
-#ifndef PRODUCT
-  void  set_scavenge_root_marked()                     { _scavenge_root_state |= sl_marked; }
-  void  clear_scavenge_root_marked()                   { _scavenge_root_state &= ~sl_marked; }
-  bool  scavenge_root_not_marked()                     { return (_scavenge_root_state &~ sl_on_list) == 0; }
-  // N.B. there is no positive marked query, and we only use the not_marked query for asserts.
-#endif //PRODUCT
-  nmethod* scavenge_root_link() const                  { return _scavenge_root_link; }
-  void     set_scavenge_root_link(nmethod *n)          { _scavenge_root_link = n; }
-
- public:
-
   // Sweeper support
   long  stack_traversal_mark()                    { return _stack_traversal_mark; }
   void  set_stack_traversal_mark(long l)          { _stack_traversal_mark = l; }
@@ -504,8 +484,6 @@
  public:
   void oops_do(OopClosure* f) { oops_do(f, false); }
   void oops_do(OopClosure* f, bool allow_zombie);
-  bool detect_scavenge_root_oops();
-  void verify_scavenge_root_oops() PRODUCT_RETURN;
 
   bool test_set_oops_do_mark();
   static void oops_do_marking_prologue();
@@ -613,7 +591,7 @@
   static int osr_entry_point_offset()             { return offset_of(nmethod, _osr_entry_point); }
   static int state_offset()                       { return offset_of(nmethod, _state); }
 
-  virtual void metadata_do(void f(Metadata*));
+  virtual void metadata_do(MetadataClosure* f);
 
   NativeCallWrapper* call_wrapper_at(address call) const;
   NativeCallWrapper* call_wrapper_before(address return_pc) const;
--- a/src/hotspot/share/compiler/compileTask.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/compiler/compileTask.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -197,13 +197,13 @@
 }
 
 // RedefineClasses support
-void CompileTask::metadata_do(void f(Metadata*)) {
+void CompileTask::metadata_do(MetadataClosure* f) {
   if (is_unloaded()) {
     return;
   }
-  f(method());
+  f->do_metadata(method());
   if (hot_method() != NULL && hot_method() != method()) {
-    f(hot_method());
+    f->do_metadata(hot_method());
   }
 }
 
--- a/src/hotspot/share/compiler/compileTask.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/compiler/compileTask.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -177,7 +177,7 @@
   bool         is_unloaded() const;
 
   // RedefineClasses support
-  void         metadata_do(void f(Metadata*));
+  void         metadata_do(MetadataClosure* f);
   void         mark_on_stack();
 
 private:
--- a/src/hotspot/share/gc/cms/cmsCardTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/cms/cmsCardTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -64,9 +64,9 @@
          "n_threads: %u > ParallelGCThreads: %u", n_threads, ParallelGCThreads);
 
   // Make sure the LNC array is valid for the space.
-  jbyte**   lowest_non_clean;
-  uintptr_t lowest_non_clean_base_chunk_index;
-  size_t    lowest_non_clean_chunk_size;
+  CardValue** lowest_non_clean;
+  uintptr_t   lowest_non_clean_base_chunk_index;
+  size_t      lowest_non_clean_chunk_size;
   get_LNC_array_for_space(sp, lowest_non_clean,
                           lowest_non_clean_base_chunk_index,
                           lowest_non_clean_chunk_size);
@@ -106,7 +106,7 @@
                jint stride, int n_strides,
                OopsInGenClosure* cl,
                CardTableRS* ct,
-               jbyte** lowest_non_clean,
+               CardValue** lowest_non_clean,
                uintptr_t lowest_non_clean_base_chunk_index,
                size_t    lowest_non_clean_chunk_size) {
   // We go from higher to lower addresses here; it wouldn't help that much
@@ -114,21 +114,19 @@
 
   // Find the first card address of the first chunk in the stride that is
   // at least "bottom" of the used region.
-  jbyte*    start_card  = byte_for(used.start());
-  jbyte*    end_card    = byte_after(used.last());
+  CardValue* start_card  = byte_for(used.start());
+  CardValue* end_card    = byte_after(used.last());
   uintptr_t start_chunk = addr_to_chunk_index(used.start());
   uintptr_t start_chunk_stride_num = start_chunk % n_strides;
-  jbyte* chunk_card_start;
+  CardValue* chunk_card_start;
 
   if ((uintptr_t)stride >= start_chunk_stride_num) {
-    chunk_card_start = (jbyte*)(start_card +
-                                (stride - start_chunk_stride_num) *
-                                ParGCCardsPerStrideChunk);
+    chunk_card_start = (start_card +
+                        (stride - start_chunk_stride_num) * ParGCCardsPerStrideChunk);
   } else {
     // Go ahead to the next chunk group boundary, then to the requested stride.
-    chunk_card_start = (jbyte*)(start_card +
-                                (n_strides - start_chunk_stride_num + stride) *
-                                ParGCCardsPerStrideChunk);
+    chunk_card_start = (start_card +
+                        (n_strides - start_chunk_stride_num + stride) * ParGCCardsPerStrideChunk);
   }
 
   while (chunk_card_start < end_card) {
@@ -139,11 +137,11 @@
     // by suitably initializing the "min_done" field in process_chunk_boundaries()
     // below, together with the dirty region extension accomplished in
     // DirtyCardToOopClosure::do_MemRegion().
-    jbyte*    chunk_card_end = chunk_card_start + ParGCCardsPerStrideChunk;
+    CardValue* chunk_card_end = chunk_card_start + ParGCCardsPerStrideChunk;
     // Invariant: chunk_mr should be fully contained within the "used" region.
-    MemRegion chunk_mr       = MemRegion(addr_for(chunk_card_start),
-                                         chunk_card_end >= end_card ?
-                                           used.end() : addr_for(chunk_card_end));
+    MemRegion chunk_mr = MemRegion(addr_for(chunk_card_start),
+                                   chunk_card_end >= end_card ?
+                                   used.end() : addr_for(chunk_card_end));
     assert(chunk_mr.word_size() > 0, "[chunk_card_start > used_end)");
     assert(used.contains(chunk_mr), "chunk_mr should be subset of used");
 
@@ -185,7 +183,7 @@
                          DirtyCardToOopClosure* dcto_cl,
                          MemRegion chunk_mr,
                          MemRegion used,
-                         jbyte** lowest_non_clean,
+                         CardValue** lowest_non_clean,
                          uintptr_t lowest_non_clean_base_chunk_index,
                          size_t    lowest_non_clean_chunk_size)
 {
@@ -224,21 +222,20 @@
     // does not scan an object straddling the mutual boundary
     // too far to the right, and attempt to scan a portion of
     // that object twice.
-    jbyte* first_dirty_card = NULL;
-    jbyte* last_card_of_first_obj =
+    CardValue* first_dirty_card = NULL;
+    CardValue* last_card_of_first_obj =
         byte_for(first_block + sp->block_size(first_block) - 1);
-    jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start());
-    jbyte* last_card_of_cur_chunk = byte_for(chunk_mr.last());
-    jbyte* last_card_to_check =
-      (jbyte*) MIN2((intptr_t) last_card_of_cur_chunk,
-                    (intptr_t) last_card_of_first_obj);
+    CardValue* first_card_of_cur_chunk = byte_for(chunk_mr.start());
+    CardValue* last_card_of_cur_chunk = byte_for(chunk_mr.last());
+    CardValue* last_card_to_check = MIN2(last_card_of_cur_chunk, last_card_of_first_obj);
     // Note that this does not need to go beyond our last card
     // if our first object completely straddles this chunk.
-    for (jbyte* cur = first_card_of_cur_chunk;
+    for (CardValue* cur = first_card_of_cur_chunk;
          cur <= last_card_to_check; cur++) {
-      jbyte val = *cur;
+      CardValue val = *cur;
       if (card_will_be_scanned(val)) {
-        first_dirty_card = cur; break;
+        first_dirty_card = cur;
+        break;
       } else {
         assert(!card_may_have_been_dirty(val), "Error");
       }
@@ -253,7 +250,7 @@
     // In this case we can help our neighbor by just asking them
     // to stop at our first card (even though it may not be dirty).
     assert(lowest_non_clean[cur_chunk_index] == NULL, "Write once : value should be stable hereafter");
-    jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start());
+    CardValue* first_card_of_cur_chunk = byte_for(chunk_mr.start());
     lowest_non_clean[cur_chunk_index] = first_card_of_cur_chunk;
   }
 
@@ -278,8 +275,8 @@
       // last_obj_card is the card corresponding to the start of the last object
       // in the chunk.  Note that the last object may not start in
       // the chunk.
-      jbyte* const last_obj_card = byte_for(last_block);
-      const jbyte val = *last_obj_card;
+      CardValue* const last_obj_card = byte_for(last_block);
+      const CardValue val = *last_obj_card;
       if (!card_will_be_scanned(val)) {
         assert(!card_may_have_been_dirty(val), "Error");
         // The card containing the head is not dirty.  Any marks on
@@ -290,20 +287,20 @@
         // The last object must be considered dirty, and extends onto the
         // following chunk.  Look for a dirty card in that chunk that will
         // bound our processing.
-        jbyte* limit_card = NULL;
+        CardValue* limit_card = NULL;
         const size_t last_block_size = sp->block_size(last_block);
-        jbyte* const last_card_of_last_obj =
+        CardValue* const last_card_of_last_obj =
           byte_for(last_block + last_block_size - 1);
-        jbyte* const first_card_of_next_chunk = byte_for(chunk_mr.end());
+        CardValue* const first_card_of_next_chunk = byte_for(chunk_mr.end());
         // This search potentially goes a long distance looking
         // for the next card that will be scanned, terminating
         // at the end of the last_block, if no earlier dirty card
         // is found.
         assert(byte_for(chunk_mr.end()) - byte_for(chunk_mr.start()) == ParGCCardsPerStrideChunk,
                "last card of next chunk may be wrong");
-        for (jbyte* cur = first_card_of_next_chunk;
+        for (CardValue* cur = first_card_of_next_chunk;
              cur <= last_card_of_last_obj; cur++) {
-          const jbyte val = *cur;
+          const CardValue val = *cur;
           if (card_will_be_scanned(val)) {
             limit_card = cur; break;
           } else {
@@ -359,7 +356,7 @@
         for (uintptr_t lnc_index = cur_chunk_index + 1;
              lnc_index <= last_chunk_index_to_check;
              lnc_index++) {
-          jbyte* lnc_card = lowest_non_clean[lnc_index];
+          CardValue* lnc_card = lowest_non_clean[lnc_index];
           if (lnc_card != NULL) {
             // we can stop at the first non-NULL entry we find
             if (lnc_card <= limit_card) {
@@ -391,7 +388,7 @@
 void
 CMSCardTable::
 get_LNC_array_for_space(Space* sp,
-                        jbyte**& lowest_non_clean,
+                        CardValue**& lowest_non_clean,
                         uintptr_t& lowest_non_clean_base_chunk_index,
                         size_t& lowest_non_clean_chunk_size) {
 
--- a/src/hotspot/share/gc/cms/cmsCardTable.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/cms/cmsCardTable.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -48,7 +48,7 @@
   // Ensures that these arrays are of sufficient size, allocating if necessary.
   // May be called by several threads concurrently.
   void get_LNC_array_for_space(Space* sp,
-                               jbyte**& lowest_non_clean,
+                               CardValue**& lowest_non_clean,
                                uintptr_t& lowest_non_clean_base_chunk_index,
                                size_t& lowest_non_clean_chunk_size);
 
@@ -59,7 +59,7 @@
                       jint stride, int n_strides,
                       OopsInGenClosure* cl,
                       CardTableRS* ct,
-                      jbyte** lowest_non_clean,
+                      CardValue** lowest_non_clean,
                       uintptr_t lowest_non_clean_base_chunk_index,
                       size_t lowest_non_clean_chunk_size);
 
@@ -70,7 +70,7 @@
                                 DirtyCardToOopClosure* dcto_cl,
                                 MemRegion chunk_mr,
                                 MemRegion used,
-                                jbyte** lowest_non_clean,
+                                CardValue** lowest_non_clean,
                                 uintptr_t lowest_non_clean_base_chunk_index,
                                 size_t    lowest_non_clean_chunk_size);
 
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -4193,9 +4193,6 @@
 
   CMSHeap* heap = CMSHeap::heap();
 
-  if (should_unload_classes()) {
-    CodeCache::gc_prologue();
-  }
   assert(haveFreelistLocks(), "must have free list locks");
   assert_lock_strong(bitMapLock());
 
@@ -4251,7 +4248,7 @@
   verify_overflow_empty();
 
   if (should_unload_classes()) {
-    CodeCache::gc_epilogue();
+    heap->prune_scavengable_nmethods();
   }
   JvmtiExport::gc_epilogue();
 
--- a/src/hotspot/share/gc/epsilon/epsilonHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -88,11 +88,6 @@
     return _space->is_in(p);
   }
 
-  virtual bool is_scavengable(oop obj) {
-    // No GC is going to happen, therefore no objects ever move.
-    return false;
-  }
-
   virtual bool is_maximal_no_gc() const {
     // No GC is going to happen. Return "we are at max", when we are about to fail.
     return used() == capacity();
--- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -58,7 +58,8 @@
   _satb_mark_queue_buffer_allocator("SATB Buffer Allocator", G1SATBBufferSize),
   _dirty_card_queue_buffer_allocator("DC Buffer Allocator", G1UpdateBufferSize),
   _satb_mark_queue_set(),
-  _dirty_card_queue_set()
+  _dirty_card_queue_set(),
+  _shared_dirty_card_queue(&_dirty_card_queue_set)
 {}
 
 void G1BarrierSet::enqueue(oop pre_val) {
@@ -91,7 +92,7 @@
   }
 }
 
-void G1BarrierSet::write_ref_field_post_slow(volatile jbyte* byte) {
+void G1BarrierSet::write_ref_field_post_slow(volatile CardValue* byte) {
   // In the slow path, we know a card is not young
   assert(*byte != G1CardTable::g1_young_card_val(), "slow path invoked without filtering");
   OrderAccess::storeload();
@@ -106,8 +107,8 @@
   if (mr.is_empty()) {
     return;
   }
-  volatile jbyte* byte = _card_table->byte_for(mr.start());
-  jbyte* last_byte = _card_table->byte_for(mr.last());
+  volatile CardValue* byte = _card_table->byte_for(mr.start());
+  CardValue* last_byte = _card_table->byte_for(mr.last());
   // skip initial young cards
   for (; byte <= last_byte && *byte == G1CardTable::g1_young_card_val(); byte++);
 
@@ -117,7 +118,7 @@
     Thread* thr = Thread::current();
     G1DirtyCardQueue& queue = G1ThreadLocalData::dirty_card_queue(thr);
     for (; byte <= last_byte; byte++) {
-      jbyte bv = *byte;
+      CardValue bv = *byte;
       if ((bv != G1CardTable::g1_young_card_val()) &&
           (bv != G1CardTable::dirty_card_val())) {
         *byte = G1CardTable::dirty_card_val();
--- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -27,9 +27,10 @@
 
 #include "gc/g1/g1DirtyCardQueue.hpp"
 #include "gc/g1/g1SATBMarkQueueSet.hpp"
+#include "gc/g1/g1SharedDirtyCardQueue.hpp"
+#include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 
-class CardTable;
 class G1CardTable;
 
 // This barrier is specialized to use a logging barrier to support
@@ -42,6 +43,7 @@
   BufferNode::Allocator _dirty_card_queue_buffer_allocator;
   G1SATBMarkQueueSet _satb_mark_queue_set;
   G1DirtyCardQueueSet _dirty_card_queue_set;
+  G1SharedDirtyCardQueue _shared_dirty_card_queue;
 
   static G1BarrierSet* g1_barrier_set() {
     return barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
@@ -73,7 +75,7 @@
 
   template <DecoratorSet decorators, typename T>
   void write_ref_field_post(T* field, oop new_val);
-  void write_ref_field_post_slow(volatile jbyte* byte);
+  void write_ref_field_post_slow(volatile CardValue* byte);
 
   virtual void on_thread_create(Thread* thread);
   virtual void on_thread_destroy(Thread* thread);
@@ -91,6 +93,10 @@
     return g1_barrier_set()->_dirty_card_queue_set;
   }
 
+  static G1SharedDirtyCardQueue& shared_dirty_card_queue() {
+    return g1_barrier_set()->_shared_dirty_card_queue;
+  }
+
   // Callbacks for runtime accesses.
   template <DecoratorSet decorators, typename BarrierSetT = G1BarrierSet>
   class AccessBarrier: public ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT> {
--- a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -47,7 +47,7 @@
 
 template <DecoratorSet decorators, typename T>
 inline void G1BarrierSet::write_ref_field_post(T* field, oop new_val) {
-  volatile jbyte* byte = _card_table->byte_for(field);
+  volatile CardValue* byte = _card_table->byte_for(field);
   if (*byte != G1CardTable::g1_young_card_val()) {
     // Take a slow path for cards in old
     write_ref_field_post_slow(byte);
--- a/src/hotspot/share/gc/g1/g1CardCounts.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1CardCounts.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -81,7 +81,7 @@
   }
 }
 
-uint G1CardCounts::add_card_count(jbyte* card_ptr) {
+uint G1CardCounts::add_card_count(CardValue* card_ptr) {
   // Returns the number of times the card has been refined.
   // If we failed to reserve/commit the counts table, return 0.
   // If card_ptr is beyond the committed end of the counts table,
@@ -116,11 +116,11 @@
 
 void G1CardCounts::clear_range(MemRegion mr) {
   if (has_count_table()) {
-    const jbyte* from_card_ptr = _ct->byte_for_const(mr.start());
+    const CardValue* from_card_ptr = _ct->byte_for_const(mr.start());
     // We use the last address in the range as the range could represent the
     // last region in the heap. In which case trying to find the card will be an
     // OOB access to the card table.
-    const jbyte* last_card_ptr = _ct->byte_for_const(mr.last());
+    const CardValue* last_card_ptr = _ct->byte_for_const(mr.last());
 
 #ifdef ASSERT
     HeapWord* start_addr = _ct->addr_for(from_card_ptr);
--- a/src/hotspot/share/gc/g1/g1CardCounts.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1CardCounts.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -54,19 +54,23 @@
 // is 'drained' during the next evacuation pause.
 
 class G1CardCounts: public CHeapObj<mtGC> {
+public:
+  typedef CardTable::CardValue CardValue;
+
+private:
   G1CardCountsMappingChangedListener _listener;
 
   G1CollectedHeap* _g1h;
   G1CardTable*     _ct;
 
   // The table of counts
-  jubyte* _card_counts;
+  uint8_t* _card_counts;
 
   // Max capacity of the reserved space for the counts table
   size_t _reserved_max_card_num;
 
   // CardTable bottom.
-  const jbyte* _ct_bot;
+  const CardValue* _ct_bot;
 
   // Returns true if the card counts table has been reserved.
   bool has_reserved_count_table() { return _card_counts != NULL; }
@@ -76,22 +80,22 @@
     return has_reserved_count_table();
   }
 
-  size_t ptr_2_card_num(const jbyte* card_ptr) {
+  size_t ptr_2_card_num(const CardValue* card_ptr) {
     assert(card_ptr >= _ct_bot,
            "Invalid card pointer: "
            "card_ptr: " PTR_FORMAT ", "
            "_ct_bot: " PTR_FORMAT,
            p2i(card_ptr), p2i(_ct_bot));
-    size_t card_num = pointer_delta(card_ptr, _ct_bot, sizeof(jbyte));
+    size_t card_num = pointer_delta(card_ptr, _ct_bot, sizeof(CardValue));
     assert(card_num < _reserved_max_card_num,
            "card pointer out of range: " PTR_FORMAT, p2i(card_ptr));
     return card_num;
   }
 
-  jbyte* card_num_2_ptr(size_t card_num) {
+  CardValue* card_num_2_ptr(size_t card_num) {
     assert(card_num < _reserved_max_card_num,
            "card num out of range: " SIZE_FORMAT, card_num);
-    return (jbyte*) (_ct_bot + card_num);
+    return (CardValue*) (_ct_bot + card_num);
   }
 
   // Clear the counts table for the given (exclusive) index range.
@@ -112,7 +116,7 @@
 
   // Increments the refinement count for the given card.
   // Returns the pre-increment count value.
-  uint add_card_count(jbyte* card_ptr);
+  uint add_card_count(CardValue* card_ptr);
 
   // Returns true if the given count is high enough to be considered
   // 'hot'; false otherwise.
--- a/src/hotspot/share/gc/g1/g1CardTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1CardTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -31,19 +31,19 @@
 #include "runtime/orderAccess.hpp"
 
 bool G1CardTable::mark_card_deferred(size_t card_index) {
-  jbyte val = _byte_map[card_index];
+  CardValue val = _byte_map[card_index];
   // It's already processed
   if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) {
     return false;
   }
 
   // Cached bit can be installed either on a clean card or on a claimed card.
-  jbyte new_val = val;
+  CardValue new_val = val;
   if (val == clean_card_val()) {
-    new_val = (jbyte)deferred_card_val();
+    new_val = deferred_card_val();
   } else {
     if (val & claimed_card_val()) {
-      new_val = val | (jbyte)deferred_card_val();
+      new_val = val | deferred_card_val();
     }
   }
   if (new_val != val) {
@@ -53,8 +53,8 @@
 }
 
 void G1CardTable::g1_mark_as_young(const MemRegion& mr) {
-  jbyte *const first = byte_for(mr.start());
-  jbyte *const last = byte_after(mr.last());
+  CardValue *const first = byte_for(mr.start());
+  CardValue *const last = byte_after(mr.last());
 
   memset_with_concurrent_readers(first, g1_young_gen, last - first);
 }
@@ -85,7 +85,7 @@
   _cur_covered_regions = 1;
   _covered[0] = _whole_heap;
 
-  _byte_map = (jbyte*) mapper->reserved().start();
+  _byte_map = (CardValue*) mapper->reserved().start();
   _byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
   assert(byte_for(low_bound) == &_byte_map[0], "Checking start of map");
   assert(byte_for(high_bound-1) <= &_byte_map[_last_valid_index], "Checking end of map");
@@ -97,6 +97,6 @@
 }
 
 bool G1CardTable::is_in_young(oop obj) const {
-  volatile jbyte* p = byte_for(obj);
+  volatile CardValue* p = byte_for(obj);
   return *p == G1CardTable::g1_young_card_val();
 }
--- a/src/hotspot/share/gc/g1/g1CardTable.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1CardTable.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -62,7 +62,7 @@
     return _byte_map[card_index] == dirty_card_val();
   }
 
-  static jbyte g1_young_card_val() { return g1_young_gen; }
+  static CardValue g1_young_card_val() { return g1_young_gen; }
 
 /*
    Claimed and deferred bits are used together in G1 during the evacuation
@@ -78,7 +78,7 @@
  */
 
   bool is_card_claimed(size_t card_index) {
-    jbyte val = _byte_map[card_index];
+    CardValue val = _byte_map[card_index];
     return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
   }
 
@@ -90,7 +90,7 @@
   bool mark_card_deferred(size_t card_index);
 
   bool is_card_deferred(size_t card_index) {
-    jbyte val = _byte_map[card_index];
+    CardValue val = _byte_map[card_index];
     return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
   }
 
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -114,7 +114,7 @@
   G1CollectedHeap* _g1h;
   G1CardTable* _g1_ct;
 
-  HeapRegion* region_for_card(jbyte* card_ptr) const {
+  HeapRegion* region_for_card(CardValue* card_ptr) const {
     return _g1h->heap_region_containing(_g1_ct->addr_for(card_ptr));
   }
 
@@ -128,7 +128,7 @@
   RedirtyLoggedCardTableEntryClosure(G1CollectedHeap* g1h) : G1CardTableEntryClosure(),
     _num_dirtied(0), _g1h(g1h), _g1_ct(g1h->card_table()) { }
 
-  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
+  bool do_card_ptr(CardValue* card_ptr, uint worker_i) {
     HeapRegion* hr = region_for_card(card_ptr);
 
     // Should only dirty cards in regions that won't be freed.
@@ -1682,12 +1682,10 @@
   // later, based on the concurrent refinement object.
   G1BarrierSet::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
                                                   &bs->dirty_card_queue_buffer_allocator(),
-                                                  Shared_DirtyCardQ_lock,
                                                   true); // init_free_ids
 
   dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
-                                    &bs->dirty_card_queue_buffer_allocator(),
-                                    Shared_DirtyCardQ_lock);
+                                    &bs->dirty_card_queue_buffer_allocator());
 
   // Create the hot card cache.
   _hot_card_cache = new G1HotCardCache(this);
@@ -2537,7 +2535,7 @@
 
   // Update common counters.
   increment_total_collections(full /* full gc */);
-  if (full) {
+  if (full || collector_state()->in_initial_mark_gc()) {
     increment_old_marking_cycles_started();
   }
 
@@ -2726,7 +2724,7 @@
         HeapRegionRemSetIterator hrrs(r->rem_set());
         size_t card_index;
         while (hrrs.has_next(card_index)) {
-          jbyte* card_ptr = (jbyte*)ct->byte_for_index(card_index);
+          CardTable::CardValue* card_ptr = ct->byte_for_index(card_index);
           // The remembered set might contain references to already freed
           // regions. Filter out such entries to avoid failing card table
           // verification.
@@ -2863,16 +2861,92 @@
 };
 
 void G1CollectedHeap::start_new_collection_set() {
+  double start = os::elapsedTime();
+
   collection_set()->start_incremental_building();
 
   clear_cset_fast_test();
 
   guarantee(_eden.length() == 0, "eden should have been cleared");
   policy()->transfer_survivors_to_cset(survivor());
+
+  // We redo the verification but now wrt to the new CSet which
+  // has just got initialized after the previous CSet was freed.
+  _cm->verify_no_collection_set_oops();
+
+  phase_times()->record_start_new_cset_time_ms((os::elapsedTime() - start) * 1000.0);
 }
 
-bool
-G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
+void G1CollectedHeap::calculate_collection_set(G1EvacuationInfo& evacuation_info, double target_pause_time_ms){
+  policy()->finalize_collection_set(target_pause_time_ms, &_survivor);
+  evacuation_info.set_collectionset_regions(collection_set()->region_length());
+
+  _cm->verify_no_collection_set_oops();
+
+  if (_hr_printer.is_active()) {
+    G1PrintCollectionSetClosure cl(&_hr_printer);
+    _collection_set.iterate(&cl);
+  }
+}
+
+G1HeapVerifier::G1VerifyType G1CollectedHeap::young_collection_verify_type() const {
+  if (collector_state()->in_initial_mark_gc()) {
+    return G1HeapVerifier::G1VerifyConcurrentStart;
+  } else if (collector_state()->in_young_only_phase()) {
+    return G1HeapVerifier::G1VerifyYoungNormal;
+  } else {
+    return G1HeapVerifier::G1VerifyMixed;
+  }
+}
+
+void G1CollectedHeap::verify_before_young_collection(G1HeapVerifier::G1VerifyType type) {
+  if (VerifyRememberedSets) {
+    log_info(gc, verify)("[Verifying RemSets before GC]");
+    VerifyRegionRemSetClosure v_cl;
+    heap_region_iterate(&v_cl);
+  }
+  _verifier->verify_before_gc(type);
+  _verifier->check_bitmaps("GC Start");
+}
+
+void G1CollectedHeap::verify_after_young_collection(G1HeapVerifier::G1VerifyType type) {
+  if (VerifyRememberedSets) {
+    log_info(gc, verify)("[Verifying RemSets after GC]");
+    VerifyRegionRemSetClosure v_cl;
+    heap_region_iterate(&v_cl);
+  }
+  _verifier->verify_after_gc(type);
+  _verifier->check_bitmaps("GC End");
+}
+
+void G1CollectedHeap::expand_heap_after_young_collection(){
+  size_t expand_bytes = _heap_sizing_policy->expansion_amount();
+  if (expand_bytes > 0) {
+    // No need for an ergo logging here,
+    // expansion_amount() does this when it returns a value > 0.
+    double expand_ms;
+    if (!expand(expand_bytes, _workers, &expand_ms)) {
+      // We failed to expand the heap. Cannot do anything about it.
+    }
+    phase_times()->record_expand_heap_time(expand_ms);
+  }
+}
+
+const char* G1CollectedHeap::young_gc_name() const {
+  if (collector_state()->in_initial_mark_gc()) {
+    return "Pause Young (Concurrent Start)";
+  } else if (collector_state()->in_young_only_phase()) {
+    if (collector_state()->in_young_gc_before_mixed()) {
+      return "Pause Young (Prepare Mixed)";
+    } else {
+      return "Pause Young (Normal)";
+    }
+  } else {
+    return "Pause Young (Mixed)";
+  }
+}
+
+bool G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
   assert_at_safepoint_on_vm_thread();
   guarantee(!is_gc_active(), "collection is not reentrant");
 
@@ -2880,16 +2954,16 @@
     return false;
   }
 
-  _gc_timer_stw->register_gc_start();
-
   GCIdMark gc_id_mark;
-  _gc_tracer_stw->report_gc_start(gc_cause(), _gc_timer_stw->gc_start());
 
   SvcGCMarker sgcm(SvcGCMarker::MINOR);
   ResourceMark rm;
 
   policy()->note_gc_start();
 
+  _gc_timer_stw->register_gc_start();
+  _gc_tracer_stw->report_gc_start(gc_cause(), _gc_timer_stw->gc_start());
+
   wait_for_root_region_scanning();
 
   print_heap_before_gc();
@@ -2909,8 +2983,7 @@
 
   // We do not allow initial-mark to be piggy-backed on a mixed GC.
   assert(!collector_state()->in_initial_mark_gc() ||
-          collector_state()->in_young_only_phase(), "sanity");
-
+         collector_state()->in_young_only_phase(), "sanity");
   // We also do not allow mixed GCs during marking.
   assert(!collector_state()->mark_or_rebuild_in_progress() || collector_state()->in_young_only_phase(), "sanity");
 
@@ -2918,39 +2991,19 @@
   // thread has completed its logging output and it's safe to signal
   // the CM thread, the flag's value in the policy has been reset.
   bool should_start_conc_mark = collector_state()->in_initial_mark_gc();
+  if (should_start_conc_mark) {
+    _cm->gc_tracer_cm()->set_gc_cause(gc_cause());
+  }
 
   // Inner scope for scope based logging, timers, and stats collection
   {
     G1EvacuationInfo evacuation_info;
 
-    if (collector_state()->in_initial_mark_gc()) {
-      // We are about to start a marking cycle, so we increment the
-      // full collection counter.
-      increment_old_marking_cycles_started();
-      _cm->gc_tracer_cm()->set_gc_cause(gc_cause());
-    }
-
     _gc_tracer_stw->report_yc_type(collector_state()->yc_type());
 
     GCTraceCPUTime tcpu;
 
-    G1HeapVerifier::G1VerifyType verify_type;
-    FormatBuffer<> gc_string("Pause Young ");
-    if (collector_state()->in_initial_mark_gc()) {
-      gc_string.append("(Concurrent Start)");
-      verify_type = G1HeapVerifier::G1VerifyConcurrentStart;
-    } else if (collector_state()->in_young_only_phase()) {
-      if (collector_state()->in_young_gc_before_mixed()) {
-        gc_string.append("(Prepare Mixed)");
-      } else {
-        gc_string.append("(Normal)");
-      }
-      verify_type = G1HeapVerifier::G1VerifyYoungNormal;
-    } else {
-      gc_string.append("(Mixed)");
-      verify_type = G1HeapVerifier::G1VerifyMixed;
-    }
-    GCTraceTime(Info, gc) tm(gc_string, NULL, gc_cause(), true);
+    GCTraceTime(Info, gc) tm(young_gc_name(), NULL, gc_cause(), true);
 
     uint active_workers = WorkerPolicy::calc_active_workers(workers()->total_workers(),
                                                             workers()->active_workers(),
@@ -2965,88 +3018,43 @@
     G1HeapTransition heap_transition(this);
     size_t heap_used_bytes_before_gc = used();
 
-    // Don't dynamically change the number of GC threads this early.  A value of
-    // 0 is used to indicate serial work.  When parallel work is done,
-    // it will be set.
-
-    { // Call to jvmpi::post_class_unload_events must occur outside of active GC
+    {
       IsGCActiveMark x;
 
       gc_prologue(false);
 
-      if (VerifyRememberedSets) {
-        log_info(gc, verify)("[Verifying RemSets before GC]");
-        VerifyRegionRemSetClosure v_cl;
-        heap_region_iterate(&v_cl);
-      }
-
-      _verifier->verify_before_gc(verify_type);
-
-      _verifier->check_bitmaps("GC Start");
-
-#if COMPILER2_OR_JVMCI
-      DerivedPointerTable::clear();
-#endif
-
-      // Please see comment in g1CollectedHeap.hpp and
-      // G1CollectedHeap::ref_processing_init() to see how
-      // reference processing currently works in G1.
-
-      // Enable discovery in the STW reference processor
-      _ref_processor_stw->enable_discovery();
+      G1HeapVerifier::G1VerifyType verify_type = young_collection_verify_type();
+      verify_before_young_collection(verify_type);
 
       {
+        // The elapsed time induced by the start time below deliberately elides
+        // the possible verification above.
+        double sample_start_time_sec = os::elapsedTime();
+
+        // Please see comment in g1CollectedHeap.hpp and
+        // G1CollectedHeap::ref_processing_init() to see how
+        // reference processing currently works in G1.
+        _ref_processor_stw->enable_discovery();
+
         // We want to temporarily turn off discovery by the
         // CM ref processor, if necessary, and turn it back on
         // on again later if we do. Using a scoped
         // NoRefDiscovery object will do this.
         NoRefDiscovery no_cm_discovery(_ref_processor_cm);
 
-        // Forget the current alloc region (we might even choose it to be part
+        policy()->record_collection_pause_start(sample_start_time_sec);
+
+        // Forget the current allocation region (we might even choose it to be part
         // of the collection set!).
         _allocator->release_mutator_alloc_region();
 
-        // This timing is only used by the ergonomics to handle our pause target.
-        // It is unclear why this should not include the full pause. We will
-        // investigate this in CR 7178365.
-        //
-        // Preserving the old comment here if that helps the investigation:
-        //
-        // The elapsed time induced by the start time below deliberately elides
-        // the possible verification above.
-        double sample_start_time_sec = os::elapsedTime();
-
-        policy()->record_collection_pause_start(sample_start_time_sec);
-
-        if (collector_state()->in_initial_mark_gc()) {
-          concurrent_mark()->pre_initial_mark();
-        }
-
-        policy()->finalize_collection_set(target_pause_time_ms, &_survivor);
-
-        evacuation_info.set_collectionset_regions(collection_set()->region_length());
-
-        register_humongous_regions_with_cset();
-
-        assert(_verifier->check_cset_fast_test(), "Inconsistency in the InCSetState table.");
-
-        // We call this after finalize_cset() to
-        // ensure that the CSet has been finalized.
-        _cm->verify_no_cset_oops();
-
-        if (_hr_printer.is_active()) {
-          G1PrintCollectionSetClosure cl(&_hr_printer);
-          _collection_set.iterate(&cl);
-        }
-
-        // Initialize the GC alloc regions.
-        _allocator->init_gc_alloc_regions(evacuation_info);
+        calculate_collection_set(evacuation_info, target_pause_time_ms);
 
         G1ParScanThreadStateSet per_thread_states(this,
                                                   workers()->active_workers(),
                                                   collection_set()->young_region_length(),
                                                   collection_set()->optional_region_length());
-        pre_evacuate_collection_set();
+        pre_evacuate_collection_set(evacuation_info);
 
         // Actually do the work...
         evacuate_collection_set(&per_thread_states);
@@ -3054,39 +3062,12 @@
 
         post_evacuate_collection_set(evacuation_info, &per_thread_states);
 
-        const size_t* surviving_young_words = per_thread_states.surviving_young_words();
-        free_collection_set(&_collection_set, evacuation_info, surviving_young_words);
-
-        eagerly_reclaim_humongous_regions();
-
-        record_obj_copy_mem_stats();
+        start_new_collection_set();
+
         _survivor_evac_stats.adjust_desired_plab_sz();
         _old_evac_stats.adjust_desired_plab_sz();
 
-        double start = os::elapsedTime();
-        start_new_collection_set();
-        phase_times()->record_start_new_cset_time_ms((os::elapsedTime() - start) * 1000.0);
-
-        if (evacuation_failed()) {
-          double recalculate_used_start = os::elapsedTime();
-          set_used(recalculate_used());
-          phase_times()->record_evac_fail_recalc_used_time((os::elapsedTime() - recalculate_used_start) * 1000.0);
-
-          if (_archive_allocator != NULL) {
-            _archive_allocator->clear_used();
-          }
-          for (uint i = 0; i < ParallelGCThreads; i++) {
-            if (_evacuation_failed_info_array[i].has_failed()) {
-              _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]);
-            }
-          }
-        } else {
-          // The "used" of the the collection set have already been subtracted
-          // when they were freed.  Add in the bytes evacuated.
-          increase_used(policy()->bytes_copied_during_gc());
-        }
-
-        if (collector_state()->in_initial_mark_gc()) {
+        if (should_start_conc_mark) {
           // We have to do this before we notify the CM threads that
           // they can start working to make sure that all the
           // appropriate initialization is done on the CM object.
@@ -3100,50 +3081,16 @@
 
         _allocator->init_mutator_alloc_region();
 
-        {
-          size_t expand_bytes = _heap_sizing_policy->expansion_amount();
-          if (expand_bytes > 0) {
-            size_t bytes_before = capacity();
-            // No need for an ergo logging here,
-            // expansion_amount() does this when it returns a value > 0.
-            double expand_ms;
-            if (!expand(expand_bytes, _workers, &expand_ms)) {
-              // We failed to expand the heap. Cannot do anything about it.
-            }
-            phase_times()->record_expand_heap_time(expand_ms);
-          }
-        }
-
-        // We redo the verification but now wrt to the new CSet which
-        // has just got initialized after the previous CSet was freed.
-        _cm->verify_no_cset_oops();
-
-        // This timing is only used by the ergonomics to handle our pause target.
-        // It is unclear why this should not include the full pause. We will
-        // investigate this in CR 7178365.
+        expand_heap_after_young_collection();
+
         double sample_end_time_sec = os::elapsedTime();
         double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
         size_t total_cards_scanned = phase_times()->sum_thread_work_items(G1GCPhaseTimes::ScanRS, G1GCPhaseTimes::ScanRSScannedCards);
         policy()->record_collection_pause_end(pause_time_ms, total_cards_scanned, heap_used_bytes_before_gc);
-
-        evacuation_info.set_collectionset_used_before(collection_set()->bytes_used_before());
-        evacuation_info.set_bytes_copied(policy()->bytes_copied_during_gc());
-
-        if (VerifyRememberedSets) {
-          log_info(gc, verify)("[Verifying RemSets after GC]");
-          VerifyRegionRemSetClosure v_cl;
-          heap_region_iterate(&v_cl);
-        }
-
-        _verifier->verify_after_gc(verify_type);
-        _verifier->check_bitmaps("GC End");
-
-        assert(!_ref_processor_stw->discovery_enabled(), "Postcondition");
-        _ref_processor_stw->verify_no_references_recorded();
-
-        // CM reference discovery will be re-enabled if necessary.
       }
 
+      verify_after_young_collection(verify_type);
+
 #ifdef TRACESPINNING
       ParallelTaskTerminator::print_termination_counts();
 #endif
@@ -3159,11 +3106,6 @@
     policy()->print_phases();
     heap_transition.print();
 
-    // It is not yet to safe to tell the concurrent mark to
-    // start as we have some optional output below. We don't want the
-    // output from the concurrent mark thread interfering with this
-    // logging output either.
-
     _hrm->verify_optional();
     _verifier->verify_region_sets_optional();
 
@@ -3190,13 +3132,11 @@
   // that came from the pause.
 
   if (should_start_conc_mark) {
-    // CAUTION: after the doConcurrentMark() call below,
-    // the concurrent marking thread(s) could be running
-    // concurrently with us. Make sure that anything after
-    // this point does not assume that we are the only GC thread
-    // running. Note: of course, the actual marking work will
-    // not start until the safepoint itself is released in
-    // SuspendibleThreadSet::desynchronize().
+    // CAUTION: after the doConcurrentMark() call below, the concurrent marking
+    // thread(s) could be running concurrently with us. Make sure that anything
+    // after this point does not assume that we are the only GC thread running.
+    // Note: of course, the actual marking work will not start until the safepoint
+    // itself is released in SuspendibleThreadSet::desynchronize().
     do_concurrent_mark();
   }
 
@@ -3677,6 +3617,7 @@
 
   make_pending_list_reachable();
 
+  assert(!rp->discovery_enabled(), "Postcondition");
   rp->verify_no_references_recorded();
 
   double ref_proc_time = os::elapsedTime() - ref_proc_start;
@@ -3699,7 +3640,7 @@
   phase_times()->record_merge_pss_time_ms((os::elapsedTime() - merge_pss_time_start) * 1000.0);
 }
 
-void G1CollectedHeap::pre_evacuate_collection_set() {
+void G1CollectedHeap::pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info) {
   _expand_heap_after_alloc_failure = true;
   _evacuation_failed = false;
 
@@ -3707,11 +3648,23 @@
   _hot_card_cache->reset_hot_cache_claimed_index();
   _hot_card_cache->set_use_cache(false);
 
+  // Initialize the GC alloc regions.
+  _allocator->init_gc_alloc_regions(evacuation_info);
+
+  register_humongous_regions_with_cset();
+  assert(_verifier->check_cset_fast_test(), "Inconsistency in the InCSetState table.");
+
   rem_set()->prepare_for_oops_into_collection_set_do();
   _preserved_marks_set.assert_empty();
 
+#if COMPILER2_OR_JVMCI
+  DerivedPointerTable::clear();
+#endif
+
   // InitialMark needs claim bits to keep track of the marked-through CLDs.
   if (collector_state()->in_initial_mark_gc()) {
+    concurrent_mark()->pre_initial_mark();
+
     double start_clear_claimed_marks = os::elapsedTime();
 
     ClassLoaderDataGraph::clear_claimed_marks();
@@ -3918,19 +3871,34 @@
     phase_times()->record_string_deduplication_time(string_cleanup_time_ms);
   }
 
+  _allocator->release_gc_alloc_regions(evacuation_info);
+
   if (evacuation_failed()) {
     restore_after_evac_failure();
 
     // Reset the G1EvacuationFailureALot counters and flags
-    // Note: the values are reset only when an actual
-    // evacuation failure occurs.
     NOT_PRODUCT(reset_evacuation_should_fail();)
+
+    double recalculate_used_start = os::elapsedTime();
+    set_used(recalculate_used());
+    phase_times()->record_evac_fail_recalc_used_time((os::elapsedTime() - recalculate_used_start) * 1000.0);
+
+    if (_archive_allocator != NULL) {
+      _archive_allocator->clear_used();
+    }
+    for (uint i = 0; i < ParallelGCThreads; i++) {
+      if (_evacuation_failed_info_array[i].has_failed()) {
+        _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]);
+      }
+    }
+  } else {
+    // The "used" of the the collection set have already been subtracted
+    // when they were freed.  Add in the bytes evacuated.
+    increase_used(policy()->bytes_copied_during_gc());
   }
 
   _preserved_marks_set.assert_empty();
 
-  _allocator->release_gc_alloc_regions(evacuation_info);
-
   merge_per_thread_state_info(per_thread_states);
 
   // Reset and re-enable the hot card cache.
@@ -3942,6 +3910,16 @@
   purge_code_root_memory();
 
   redirty_logged_cards();
+
+  free_collection_set(&_collection_set, evacuation_info, per_thread_states->surviving_young_words());
+
+  eagerly_reclaim_humongous_regions();
+
+  record_obj_copy_mem_stats();
+
+  evacuation_info.set_collectionset_used_before(collection_set()->bytes_used_before());
+  evacuation_info.set_bytes_copied(policy()->bytes_copied_during_gc());
+
 #if COMPILER2_OR_JVMCI
   double start = os::elapsedTime();
   DerivedPointerTable::update_pointers();
@@ -4796,13 +4774,6 @@
   void do_oop(narrowOop* p) { do_oop_work(p); }
 };
 
-// Returns true if the reference points to an object that
-// can move in an incremental collection.
-bool G1CollectedHeap::is_scavengable(oop obj) {
-  HeapRegion* hr = heap_region_containing(obj);
-  return !hr->is_pinned();
-}
-
 void G1CollectedHeap::register_nmethod(nmethod* nm) {
   guarantee(nm != NULL, "sanity");
   RegisterNMethodOopClosure reg_cl(this, nm);
@@ -4835,9 +4806,7 @@
       return;
     }
 
-    if (ScavengeRootsInCode) {
-      _g1h->register_nmethod(nm);
-    }
+    _g1h->register_nmethod(nm);
   }
 };
 
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -357,6 +357,8 @@
     assert(Thread::current()->is_VM_thread(), "current thread is not VM thread"); \
   } while (0)
 
+  const char* young_gc_name() const;
+
   // The young region list.
   G1EdenRegions _eden;
   G1SurvivorRegions _survivor;
@@ -730,14 +732,21 @@
   // to the GC locker being active, true otherwise
   bool do_collection_pause_at_safepoint(double target_pause_time_ms);
 
+  G1HeapVerifier::G1VerifyType young_collection_verify_type() const;
+  void verify_before_young_collection(G1HeapVerifier::G1VerifyType type);
+  void verify_after_young_collection(G1HeapVerifier::G1VerifyType type);
+
+  void calculate_collection_set(G1EvacuationInfo& evacuation_info, double target_pause_time_ms);
+
   // Actually do the work of evacuating the collection set.
   void evacuate_collection_set(G1ParScanThreadStateSet* per_thread_states);
   void evacuate_optional_collection_set(G1ParScanThreadStateSet* per_thread_states);
   void evacuate_optional_regions(G1ParScanThreadStateSet* per_thread_states, G1OptionalCSet* ocset);
 
-  void pre_evacuate_collection_set();
+  void pre_evacuate_collection_set(G1EvacuationInfo& evacuation_info);
   void post_evacuate_collection_set(G1EvacuationInfo& evacuation_info, G1ParScanThreadStateSet* pss);
 
+  void expand_heap_after_young_collection();
   // Update object copying statistics.
   void record_obj_copy_mem_stats();
 
@@ -1307,9 +1316,6 @@
 
   // Optimized nmethod scanning support routines
 
-  // Is an oop scavengeable
-  virtual bool is_scavengable(oop obj);
-
   // Register the given nmethod with the G1 heap.
   virtual void register_nmethod(nmethod* nm);
 
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -734,7 +734,9 @@
 };
 
 void G1ConcurrentMark::pre_initial_mark() {
-  // Initialize marking structures. This has to be done in a STW phase.
+  assert_at_safepoint_on_vm_thread();
+
+  // Reset marking state.
   reset();
 
   // For each region note start of marking.
@@ -1944,7 +1946,7 @@
   }
 };
 
-void G1ConcurrentMark::verify_no_cset_oops() {
+void G1ConcurrentMark::verify_no_collection_set_oops() {
   assert(SafepointSynchronize::is_at_safepoint(), "should be at a safepoint");
   if (!_g1h->collector_state()->mark_or_rebuild_in_progress()) {
     return;
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -579,7 +579,7 @@
   // Verify that there are no collection set oops on the stacks (taskqueues /
   // global mark stack) and fingers (global / per-task).
   // If marking is not in progress, it's a no-op.
-  void verify_no_cset_oops() PRODUCT_RETURN;
+  void verify_no_collection_set_oops() PRODUCT_RETURN;
 
   inline bool do_yield_check();
 
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -44,7 +44,7 @@
 // SuspendibleThreadSet after every card.
 class G1RefineCardConcurrentlyClosure: public G1CardTableEntryClosure {
 public:
-  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
+  bool do_card_ptr(CardValue* card_ptr, uint worker_i) {
     G1CollectedHeap::heap()->rem_set()->refine_card_concurrently(card_ptr, worker_i);
 
     if (SuspendibleThreadSet::should_yield()) {
@@ -56,21 +56,18 @@
   }
 };
 
-G1DirtyCardQueue::G1DirtyCardQueue(G1DirtyCardQueueSet* qset, bool permanent) :
+G1DirtyCardQueue::G1DirtyCardQueue(G1DirtyCardQueueSet* qset) :
   // Dirty card queues are always active, so we create them with their
   // active field set to true.
-  PtrQueue(qset, permanent, true /* active */)
+  PtrQueue(qset, true /* active */)
 { }
 
 G1DirtyCardQueue::~G1DirtyCardQueue() {
-  if (!is_permanent()) {
-    flush();
-  }
+  flush();
 }
 
 G1DirtyCardQueueSet::G1DirtyCardQueueSet(bool notify_when_complete) :
   PtrQueueSet(notify_when_complete),
-  _shared_dirty_card_queue(this, true /* permanent */),
   _free_ids(NULL),
   _processed_buffers_mut(0),
   _processed_buffers_rs_thread(0),
@@ -90,10 +87,8 @@
 
 void G1DirtyCardQueueSet::initialize(Monitor* cbl_mon,
                                      BufferNode::Allocator* allocator,
-                                     Mutex* lock,
                                      bool init_free_ids) {
   PtrQueueSet::initialize(cbl_mon, allocator);
-  _shared_dirty_card_queue.set_lock(lock);
   if (init_free_ids) {
     _free_ids = new G1FreeIdSet(0, num_par_ids());
   }
@@ -113,7 +108,7 @@
   size_t i = node->index();
   size_t limit = buffer_size();
   for ( ; i < limit; ++i) {
-    jbyte* card_ptr = static_cast<jbyte*>(buf[i]);
+    CardTable::CardValue* card_ptr = static_cast<CardTable::CardValue*>(buf[i]);
     assert(card_ptr != NULL, "invariant");
     if (!cl->do_card_ptr(card_ptr, worker_i)) {
       result = false;           // Incomplete processing.
@@ -217,13 +212,7 @@
   } closure;
   Threads::threads_do(&closure);
 
-  shared_dirty_card_queue()->reset();
-}
-
-void G1DirtyCardQueueSet::concatenate_log(G1DirtyCardQueue& dcq) {
-  if (!dcq.is_empty()) {
-    dcq.flush();
-  }
+  G1BarrierSet::shared_dirty_card_queue().reset();
 }
 
 void G1DirtyCardQueueSet::concatenate_logs() {
@@ -234,16 +223,16 @@
   size_t old_limit = max_completed_buffers();
   set_max_completed_buffers(MaxCompletedBuffersUnlimited);
 
-  class ConcatenateThreadLogClosure : public ThreadClosure {
-    G1DirtyCardQueueSet* _qset;
-  public:
-    ConcatenateThreadLogClosure(G1DirtyCardQueueSet* qset) : _qset(qset) {}
+  struct ConcatenateThreadLogClosure : public ThreadClosure {
     virtual void do_thread(Thread* t) {
-      _qset->concatenate_log(G1ThreadLocalData::dirty_card_queue(t));
+      G1DirtyCardQueue& dcq = G1ThreadLocalData::dirty_card_queue(t);
+      if (!dcq.is_empty()) {
+        dcq.flush();
+      }
     }
-  } closure(this);
+  } closure;
   Threads::threads_do(&closure);
 
-  concatenate_log(_shared_dirty_card_queue);
+  G1BarrierSet::shared_dirty_card_queue().flush();
   set_max_completed_buffers(old_limit);
 }
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -25,6 +25,7 @@
 #ifndef SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP
 #define SHARE_GC_G1_G1DIRTYCARDQUEUE_HPP
 
+#include "gc/shared/cardTable.hpp"
 #include "gc/shared/ptrQueue.hpp"
 #include "memory/allocation.hpp"
 
@@ -37,15 +38,17 @@
 // require these closure objects to be stack-allocated.
 class G1CardTableEntryClosure: public CHeapObj<mtGC> {
 public:
+  typedef CardTable::CardValue CardValue;
+
   // Process the card whose card table entry is "card_ptr".  If returns
   // "false", terminate the iteration early.
-  virtual bool do_card_ptr(jbyte* card_ptr, uint worker_i) = 0;
+  virtual bool do_card_ptr(CardValue* card_ptr, uint worker_i) = 0;
 };
 
 // A ptrQueue whose elements are "oops", pointers to object heads.
 class G1DirtyCardQueue: public PtrQueue {
 public:
-  G1DirtyCardQueue(G1DirtyCardQueueSet* qset, bool permanent = false);
+  G1DirtyCardQueue(G1DirtyCardQueueSet* qset);
 
   // Flush before destroying; queue may be used to capture pending work while
   // doing something else, with auto-flush on completion.
@@ -67,11 +70,7 @@
 
 };
 
-
-
 class G1DirtyCardQueueSet: public PtrQueueSet {
-  G1DirtyCardQueue _shared_dirty_card_queue;
-
   // Apply the closure to the elements of "node" from it's index to
   // buffer_size.  If all closure applications return true, then
   // returns true.  Stops processing after the first closure
@@ -113,15 +112,12 @@
   // Current buffer node used for parallel iteration.
   BufferNode* volatile _cur_par_buffer_node;
 
-  void concatenate_log(G1DirtyCardQueue& dcq);
-
 public:
   G1DirtyCardQueueSet(bool notify_when_complete = true);
   ~G1DirtyCardQueueSet();
 
   void initialize(Monitor* cbl_mon,
                   BufferNode::Allocator* allocator,
-                  Mutex* lock,
                   bool init_free_ids = false);
 
   // The number of parallel ids that can be claimed to allow collector or
@@ -144,10 +140,6 @@
   // by reset_for_par_iteration.
   void par_apply_closure_to_all_completed_buffers(G1CardTableEntryClosure* cl);
 
-  G1DirtyCardQueue* shared_dirty_card_queue() {
-    return &_shared_dirty_card_queue;
-  }
-
   // If a full collection is happening, reset partial logs, and ignore
   // completed ones: the full collection will make them all irrelevant.
   void abandon_logs();
--- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -64,7 +64,7 @@
     }
     size_t card_index = _ct->index_for(p);
     if (_ct->mark_card_deferred(card_index)) {
-      _dcq->enqueue((jbyte*)_ct->byte_for_index(card_index));
+      _dcq->enqueue(_ct->byte_for_index(card_index));
     }
   }
 };
--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -152,10 +152,6 @@
   reference_processor()->enable_discovery();
   reference_processor()->setup_policy(scope()->should_clear_soft_refs());
 
-  // When collecting the permanent generation Method*s may be moving,
-  // so we either have to flush all bcp data or convert it into bci.
-  CodeCache::gc_prologue();
-
   // We should save the marks of the currently locked biased monitors.
   // The marking doesn't preserve the marks of biased objects.
   BiasedLocking::preserve_marks();
@@ -187,7 +183,6 @@
   update_derived_pointers();
 
   BiasedLocking::restore_marks();
-  CodeCache::gc_epilogue();
   JvmtiExport::gc_epilogue();
 
   _heap->prepare_heap_for_mutators();
--- a/src/hotspot/share/gc/g1/g1HotCardCache.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1HotCardCache.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -39,7 +39,7 @@
     _use_cache = true;
 
     _hot_cache_size = (size_t)1 << G1ConcRSLogCacheSize;
-    _hot_cache = ArrayAllocator<jbyte*>::allocate(_hot_cache_size, mtGC);
+    _hot_cache = ArrayAllocator<CardValue*>::allocate(_hot_cache_size, mtGC);
 
     reset_hot_cache_internal();
 
@@ -54,12 +54,12 @@
 G1HotCardCache::~G1HotCardCache() {
   if (default_use_cache()) {
     assert(_hot_cache != NULL, "Logic");
-    ArrayAllocator<jbyte*>::free(_hot_cache, _hot_cache_size);
+    ArrayAllocator<CardValue*>::free(_hot_cache, _hot_cache_size);
     _hot_cache = NULL;
   }
 }
 
-jbyte* G1HotCardCache::insert(jbyte* card_ptr) {
+CardTable::CardValue* G1HotCardCache::insert(CardValue* card_ptr) {
   uint count = _card_counts.add_card_count(card_ptr);
   if (!_card_counts.is_hot(count)) {
     // The card is not hot so do not store it in the cache;
@@ -69,7 +69,7 @@
   // Otherwise, the card is hot.
   size_t index = Atomic::add(1u, &_hot_cache_idx) - 1;
   size_t masked_index = index & (_hot_cache_size - 1);
-  jbyte* current_ptr = _hot_cache[masked_index];
+  CardValue* current_ptr = _hot_cache[masked_index];
 
   // Try to store the new card pointer into the cache. Compare-and-swap to guard
   // against the unlikely event of a race resulting in another card pointer to
@@ -77,9 +77,9 @@
   // card_ptr in favor of the other option, which would be starting over. This
   // should be OK since card_ptr will likely be the older card already when/if
   // this ever happens.
-  jbyte* previous_ptr = Atomic::cmpxchg(card_ptr,
-                                        &_hot_cache[masked_index],
-                                        current_ptr);
+  CardValue* previous_ptr = Atomic::cmpxchg(card_ptr,
+                                            &_hot_cache[masked_index],
+                                            current_ptr);
   return (previous_ptr == current_ptr) ? previous_ptr : card_ptr;
 }
 
@@ -96,7 +96,7 @@
     // The current worker has successfully claimed the chunk [start_idx..end_idx)
     end_idx = MIN2(end_idx, _hot_cache_size);
     for (size_t i = start_idx; i < end_idx; i++) {
-      jbyte* card_ptr = _hot_cache[i];
+      CardValue* card_ptr = _hot_cache[i];
       if (card_ptr != NULL) {
         bool result = cl->do_card_ptr(card_ptr, worker_i);
         assert(result, "Closure should always return true");
--- a/src/hotspot/share/gc/g1/g1HotCardCache.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1HotCardCache.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -53,7 +53,10 @@
 // code, increasing throughput.
 
 class G1HotCardCache: public CHeapObj<mtGC> {
+public:
+  typedef CardTable::CardValue CardValue;
 
+private:
   G1CollectedHeap*  _g1h;
 
   bool              _use_cache;
@@ -62,7 +65,7 @@
 
 
   // The card cache table
-  jbyte**           _hot_cache;
+  CardValue** _hot_cache;
 
   size_t            _hot_cache_size;
 
@@ -107,7 +110,7 @@
   // adding, NULL is returned and no further action in needed.
   // If we evict a card from the cache to make room for the new card,
   // the evicted card is then returned for refinement.
-  jbyte* insert(jbyte* card_ptr);
+  CardValue* insert(CardValue* card_ptr);
 
   // Refine the cards that have delayed as a result of
   // being in the cache.
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -120,7 +120,7 @@
     size_t card_index = ct()->index_for(p);
     // If the card hasn't been added to the buffer, do it.
     if (ct()->mark_card_deferred(card_index)) {
-      dirty_card_queue().enqueue((jbyte*)ct()->byte_for_index(card_index));
+      dirty_card_queue().enqueue(ct()->byte_for_index(card_index));
     }
   }
 
--- a/src/hotspot/share/gc/g1/g1Policy.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1188,9 +1188,11 @@
   return (uint) result;
 }
 
-void G1Policy::finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor) {
+uint G1Policy::finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor) {
   double time_remaining_ms = _collection_set->finalize_young_part(target_pause_time_ms, survivor);
   _collection_set->finalize_old_part(time_remaining_ms);
+
+  return _collection_set->region_length();
 }
 
 void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) {
--- a/src/hotspot/share/gc/g1/g1Policy.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -344,7 +344,7 @@
   bool next_gc_should_be_mixed(const char* true_action_str,
                                const char* false_action_str) const;
 
-  void finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor);
+  uint finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor);
 private:
   // Set the state to start a concurrent marking cycle and clear
   // _initiate_conc_mark_if_possible because it has now been
--- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -205,8 +205,10 @@
                                                          MemoryType type) :
   G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, commit_factor, type),
   _rs(rs),
+  _dram_mapper(NULL),
   _num_committed_dram(0),
   _num_committed_nvdimm(0),
+  _start_index_of_dram(0),
   _page_size(page_size),
   _commit_factor(commit_factor),
   _type(type) {
@@ -248,7 +250,6 @@
     _dram_mapper = new G1RegionsSmallerThanCommitSizeMapper(rs_dram, rs_dram.size(), _page_size, _region_granularity, _commit_factor, _type);
   }
 
-  _start_index_of_nvdimm = 0;
   _start_index_of_dram = (uint)(rs_nvdimm.size() / _region_granularity);
   return true;
 }
--- a/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1RegionToSpaceMapper.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -101,12 +101,10 @@
 // part of space is mapped to dram and part to nv-dimm
 class G1RegionToHeteroSpaceMapper : public G1RegionToSpaceMapper {
 private:
-  size_t _pages_per_region;
   ReservedSpace _rs;
   G1RegionToSpaceMapper* _dram_mapper;
   uint _num_committed_dram;
   uint _num_committed_nvdimm;
-  uint _start_index_of_nvdimm;
   uint _start_index_of_dram;
   size_t _page_size;
   size_t _commit_factor;
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -35,6 +35,7 @@
 #include "gc/g1/g1OopClosures.inline.hpp"
 #include "gc/g1/g1RootClosures.hpp"
 #include "gc/g1/g1RemSet.hpp"
+#include "gc/g1/g1SharedDirtyCardQueue.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionManager.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
@@ -114,12 +115,9 @@
   // information. These are also called "dirty". Valid entries are from [0.._cur_dirty_region)
   uint* _dirty_region_buffer;
 
-  typedef jbyte IsDirtyRegionState;
-  static const IsDirtyRegionState Clean = 0;
-  static const IsDirtyRegionState Dirty = 1;
-  // Holds a flag for every region whether it is in the _dirty_region_buffer already
-  // to avoid duplicates. Uses jbyte since there are no atomic instructions for bools.
-  IsDirtyRegionState* _in_dirty_region_buffer;
+  // Flag for every region whether it is in the _dirty_region_buffer already
+  // to avoid duplicates.
+  bool volatile* _in_dirty_region_buffer;
   size_t _cur_dirty_region;
 
   // Creates a snapshot of the current _top values at the start of collection to
@@ -169,7 +167,7 @@
       FREE_C_HEAP_ARRAY(uint, _dirty_region_buffer);
     }
     if (_in_dirty_region_buffer != NULL) {
-      FREE_C_HEAP_ARRAY(IsDirtyRegionState, _in_dirty_region_buffer);
+      FREE_C_HEAP_ARRAY(bool, _in_dirty_region_buffer);
     }
     if (_scan_top != NULL) {
       FREE_C_HEAP_ARRAY(HeapWord*, _scan_top);
@@ -183,7 +181,7 @@
     _iter_states = NEW_C_HEAP_ARRAY(G1RemsetIterState, max_regions, mtGC);
     _iter_claims = NEW_C_HEAP_ARRAY(size_t, max_regions, mtGC);
     _dirty_region_buffer = NEW_C_HEAP_ARRAY(uint, max_regions, mtGC);
-    _in_dirty_region_buffer = NEW_C_HEAP_ARRAY(IsDirtyRegionState, max_regions, mtGC);
+    _in_dirty_region_buffer = NEW_C_HEAP_ARRAY(bool, max_regions, mtGC);
     _scan_top = NEW_C_HEAP_ARRAY(HeapWord*, max_regions, mtGC);
   }
 
@@ -197,7 +195,7 @@
     G1CollectedHeap::heap()->heap_region_iterate(&cl);
 
     memset((void*)_iter_claims, 0, _max_regions * sizeof(size_t));
-    memset(_in_dirty_region_buffer, Clean, _max_regions * sizeof(IsDirtyRegionState));
+    memset((void*)_in_dirty_region_buffer, false, _max_regions * sizeof(bool));
     _cur_dirty_region = 0;
   }
 
@@ -241,12 +239,11 @@
   }
 
   void add_dirty_region(uint region) {
-    if (_in_dirty_region_buffer[region] == Dirty) {
+    if (_in_dirty_region_buffer[region]) {
       return;
     }
 
-    bool marked_as_dirty = Atomic::cmpxchg(Dirty, &_in_dirty_region_buffer[region], Clean) == Clean;
-    if (marked_as_dirty) {
+    if (!Atomic::cmpxchg(true, &_in_dirty_region_buffer[region], false)) {
       size_t allocated = Atomic::add(1u, &_cur_dirty_region) - 1;
       _dirty_region_buffer[allocated] = region;
     }
@@ -470,7 +467,7 @@
     _g1rs(g1h->rem_set()), _update_rs_cl(update_rs_cl), _cards_scanned(0), _cards_skipped(0)
   {}
 
-  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
+  bool do_card_ptr(CardValue* card_ptr, uint worker_i) {
     // The only time we care about recording cards that
     // contain references that point into the collection set
     // is during RSet updating within an evacuation pause.
@@ -523,9 +520,7 @@
 }
 
 void G1RemSet::prepare_for_oops_into_collection_set_do() {
-  G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
-  dcqs.concatenate_logs();
-
+  G1BarrierSet::dirty_card_queue_set().concatenate_logs();
   _scan_state->reset();
 }
 
@@ -538,7 +533,7 @@
   phase_times->record_clear_ct_time((os::elapsedTime() - start) * 1000.0);
 }
 
-inline void check_card_ptr(jbyte* card_ptr, G1CardTable* ct) {
+inline void check_card_ptr(CardTable::CardValue* card_ptr, G1CardTable* ct) {
 #ifdef ASSERT
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   assert(g1h->is_in_exact(ct->addr_for(card_ptr)),
@@ -550,7 +545,7 @@
 #endif
 }
 
-void G1RemSet::refine_card_concurrently(jbyte* card_ptr,
+void G1RemSet::refine_card_concurrently(CardValue* card_ptr,
                                         uint worker_i) {
   assert(!_g1h->is_gc_active(), "Only call concurrently");
 
@@ -606,7 +601,7 @@
   if (_hot_card_cache->use_cache()) {
     assert(!SafepointSynchronize::is_at_safepoint(), "sanity");
 
-    const jbyte* orig_card_ptr = card_ptr;
+    const CardValue* orig_card_ptr = card_ptr;
     card_ptr = _hot_card_cache->insert(card_ptr);
     if (card_ptr == NULL) {
       // There was no eviction. Nothing to do.
@@ -647,7 +642,7 @@
   // Okay to clean and process the card now.  There are still some
   // stale card cases that may be detected by iteration and dealt with
   // as iteration failure.
-  *const_cast<volatile jbyte*>(card_ptr) = G1CardTable::clean_card_val();
+  *const_cast<volatile CardValue*>(card_ptr) = G1CardTable::clean_card_val();
 
   // This fence serves two purposes.  First, the card must be cleaned
   // before processing the contents.  Second, we can't proceed with
@@ -664,32 +659,33 @@
   assert(!dirty_region.is_empty(), "sanity");
 
   G1ConcurrentRefineOopClosure conc_refine_cl(_g1h, worker_i);
-
-  bool card_processed =
-    r->oops_on_card_seq_iterate_careful<false>(dirty_region, &conc_refine_cl);
+  if (r->oops_on_card_seq_iterate_careful<false>(dirty_region, &conc_refine_cl)) {
+    _num_conc_refined_cards++; // Unsynchronized update, only used for logging.
+    return;
+  }
 
   // If unable to process the card then we encountered an unparsable
-  // part of the heap (e.g. a partially allocated object) while
-  // processing a stale card.  Despite the card being stale, redirty
-  // and re-enqueue, because we've already cleaned the card.  Without
-  // this we could incorrectly discard a non-stale card.
-  if (!card_processed) {
-    // The card might have gotten re-dirtied and re-enqueued while we
-    // worked.  (In fact, it's pretty likely.)
-    if (*card_ptr != G1CardTable::dirty_card_val()) {
-      *card_ptr = G1CardTable::dirty_card_val();
-      MutexLockerEx x(Shared_DirtyCardQ_lock,
-                      Mutex::_no_safepoint_check_flag);
-      G1DirtyCardQueue* sdcq =
-        G1BarrierSet::dirty_card_queue_set().shared_dirty_card_queue();
-      sdcq->enqueue(card_ptr);
-    }
-  } else {
-    _num_conc_refined_cards++; // Unsynchronized update, only used for logging.
+  // part of the heap (e.g. a partially allocated object, so only
+  // temporarily a problem) while processing a stale card.  Despite
+  // the card being stale, we can't simply ignore it, because we've
+  // already marked the card cleaned, so taken responsibility for
+  // ensuring the card gets scanned.
+  //
+  // However, the card might have gotten re-dirtied and re-enqueued
+  // while we worked.  (In fact, it's pretty likely.)
+  if (*card_ptr == G1CardTable::dirty_card_val()) {
+    return;
   }
+
+  // Re-dirty the card and enqueue in the *shared* queue.  Can't use
+  // the thread-local queue, because that might be the queue that is
+  // being processed by us; we could be a Java thread conscripted to
+  // perform refinement on our queue's current buffer.
+  *card_ptr = G1CardTable::dirty_card_val();
+  G1BarrierSet::shared_dirty_card_queue().enqueue(card_ptr);
 }
 
-bool G1RemSet::refine_card_during_gc(jbyte* card_ptr,
+bool G1RemSet::refine_card_during_gc(CardValue* card_ptr,
                                      G1ScanObjsDuringUpdateRSClosure* update_rs_cl) {
   assert(_g1h->is_gc_active(), "Only call during GC");
 
--- a/src/hotspot/share/gc/g1/g1RemSet.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/g1/g1RemSet.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -76,6 +76,8 @@
   G1HotCardCache*        _hot_card_cache;
 
 public:
+
+  typedef CardTable::CardValue CardValue;
   // Gives an approximation on how many threads can be expected to add records to
   // a remembered set in parallel. This can be used for sizing data structures to
   // decrease performance losses due to data structure sharing.
@@ -108,13 +110,13 @@
 
   // Refine the card corresponding to "card_ptr". Safe to be called concurrently
   // to the mutator.
-  void refine_card_concurrently(jbyte* card_ptr,
+  void refine_card_concurrently(CardValue* card_ptr,
                                 uint worker_i);
 
   // Refine the card corresponding to "card_ptr", applying the given closure to
   // all references found. Must only be called during gc.
   // Returns whether the card has been scanned.
-  bool refine_card_during_gc(jbyte* card_ptr, G1ScanObjsDuringUpdateRSClosure* update_rs_cl);
+  bool refine_card_during_gc(CardValue* card_ptr, G1ScanObjsDuringUpdateRSClosure* update_rs_cl);
 
   // Print accumulated summary info from the start of the VM.
   void print_summary_info();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/g1/g1DirtyCardQueue.hpp"
+#include "gc/g1/g1SharedDirtyCardQueue.hpp"
+#include "gc/shared/ptrQueue.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/mutexLocker.hpp"
+
+G1SharedDirtyCardQueue::G1SharedDirtyCardQueue(G1DirtyCardQueueSet* qset) :
+  _qset(qset),
+  _buffer(NULL),
+  _index(0)
+{}
+
+G1SharedDirtyCardQueue::~G1SharedDirtyCardQueue() {
+  flush();
+}
+
+void G1SharedDirtyCardQueue::enqueue(void* card_ptr) {
+  MutexLockerEx ml(Shared_DirtyCardQ_lock, Mutex::_no_safepoint_check_flag);
+  if (_index == 0) {
+    flush();
+    _buffer = _qset->allocate_buffer();
+    _index = _qset->buffer_size();
+    assert(_index != 0, "invariant");
+  }
+  _buffer[--_index] = card_ptr;
+}
+
+void G1SharedDirtyCardQueue::flush() {
+  if (_buffer != NULL) {
+    BufferNode* node = BufferNode::make_node_from_buffer(_buffer, _index);
+    _buffer = NULL;
+    _index = 0;
+    if (node->index() == _qset->buffer_size()) {
+      _qset->deallocate_buffer(node);
+    } else {
+      _qset->enqueue_completed_buffer(node);
+    }
+  }
+  assert(_index == 0, "invariant");
+}
+
+void G1SharedDirtyCardQueue::reset() {
+  if (_buffer == NULL) {
+    _index = 0;
+  } else {
+    _index = _qset->buffer_size();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_G1_G1SHAREDDIRTYCARDQUEUE_HPP
+#define SHARE_GC_G1_G1SHAREDDIRTYCARDQUEUE_HPP
+
+#include "utilities/globalDefinitions.hpp"
+
+class G1DirtyCardQueueSet;
+
+// A dirty card queue providing thread-safe enqueue.  A shared global
+// instance can be used for cases where a thread-local dirty card can't
+// be used.
+class G1SharedDirtyCardQueue {
+  G1DirtyCardQueueSet* const _qset;
+  void** _buffer;
+  size_t _index;
+
+  // Noncopyable
+  G1SharedDirtyCardQueue(const G1SharedDirtyCardQueue&);
+  G1SharedDirtyCardQueue& operator=(const G1SharedDirtyCardQueue&);
+
+public:
+  G1SharedDirtyCardQueue(G1DirtyCardQueueSet* qset);
+  ~G1SharedDirtyCardQueue();    // flushes the queue.
+
+  // Thread-safe addition to shared logging buffer.
+  void enqueue(void* card_ptr);
+
+  // Flush any pending entries to the qset and remove the buffer.
+  // Not thread-safe.
+  void flush();
+
+  // Discard any pending entries.
+  // Not thread-safe.
+  void reset();
+};
+
+#endif // SHARE_GC_G1_G1SHAREDDIRTYCARDQUEUE_HPP
--- a/src/hotspot/share/gc/parallel/adjoiningGenerations.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerations.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,7 +119,7 @@
   }
 }
 
-AdjoiningGenerations::AdjoiningGenerations() { }
+AdjoiningGenerations::AdjoiningGenerations(): _young_gen(NULL), _old_gen(NULL), _virtual_spaces(NULL) { }
 
 size_t AdjoiningGenerations::reserved_byte_size() {
   return virtual_spaces()->reserved_space().size();
--- a/src/hotspot/share/gc/parallel/adjoiningGenerations.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/adjoiningGenerations.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -50,6 +50,7 @@
   bool request_young_gen_expansion(size_t desired_change_in_bytes);
 
  protected:
+   AdjoiningGenerations();
    // The young generation and old generation, respectively
    PSYoungGen* _young_gen;
    PSOldGen* _old_gen;
@@ -59,7 +60,6 @@
 
  public:
   AdjoiningGenerations(ReservedSpace rs, GenerationSizer* policy, size_t alignment);
-  AdjoiningGenerations();
 
   // Accessors
   PSYoungGen* young_gen() { return _young_gen; }
--- a/src/hotspot/share/gc/parallel/gcTaskThread.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/gcTaskThread.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -167,7 +167,6 @@
         // so that a task can complete without waiting for idle tasks.
         // They have to be terminated separately.
         IdleGCTask::destroy((IdleGCTask*)task);
-        set_is_working(true);
       }
 
       // Check if we should release our inner resources.
--- a/src/hotspot/share/gc/parallel/gcTaskThread.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/gcTaskThread.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -47,8 +47,6 @@
   GCTaskTimeStamp* time_stamp_at(uint index);
   void add_task_timestamp(const char* name, jlong t_entry, jlong t_exit);
 
-  bool _is_working;                     // True if participating in GC tasks
-
   // Factory create and destroy methods.
   static GCTaskThread* create(GCTaskManager* manager,
                               uint           which,
@@ -85,7 +83,6 @@
   uint processor_id() const {
     return _processor_id;
   }
-  void set_is_working(bool v) { _is_working = v; }
 };
 
 class GCTaskTimeStamp : public CHeapObj<mtGC>
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -41,6 +41,7 @@
 #include "gc/shared/gcHeapSummary.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/gcWhen.hpp"
+#include "gc/shared/scavengableNMethods.hpp"
 #include "logging/log.hpp"
 #include "memory/metaspaceCounters.hpp"
 #include "oops/oop.inline.hpp"
@@ -150,6 +151,14 @@
 
 }
 
+class PSIsScavengable : public BoolObjectClosure {
+  bool do_object_b(oop obj) {
+    return ParallelScavengeHeap::heap()->is_in_young(obj);
+  }
+};
+
+static PSIsScavengable _is_scavengable;
+
 void ParallelScavengeHeap::post_initialize() {
   CollectedHeap::post_initialize();
   // Need to init the tenuring threshold
@@ -160,6 +169,8 @@
     PSMarkSweepProxy::initialize();
   }
   PSPromotionManager::initialize();
+
+  ScavengableNMethods::initialize(&_is_scavengable);
 }
 
 void ParallelScavengeHeap::update_counters() {
@@ -693,16 +704,24 @@
 }
 #endif
 
-bool ParallelScavengeHeap::is_scavengable(oop obj) {
-  return is_in_young(obj);
+void ParallelScavengeHeap::register_nmethod(nmethod* nm) {
+  ScavengableNMethods::register_nmethod(nm);
 }
 
-void ParallelScavengeHeap::register_nmethod(nmethod* nm) {
-  CodeCache::register_scavenge_root_nmethod(nm);
+void ParallelScavengeHeap::unregister_nmethod(nmethod* nm) {
+  ScavengableNMethods::unregister_nmethod(nm);
 }
 
 void ParallelScavengeHeap::verify_nmethod(nmethod* nm) {
-  CodeCache::verify_scavenge_root_nmethod(nm);
+  ScavengableNMethods::verify_nmethod(nm);
+}
+
+void ParallelScavengeHeap::flush_nmethod(nmethod* nm) {
+  // nothing particular
+}
+
+void ParallelScavengeHeap::prune_scavengable_nmethods() {
+  ScavengableNMethods::prune_nmethods();
 }
 
 GrowableArray<GCMemoryManager*> ParallelScavengeHeap::memory_managers() {
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -93,7 +93,15 @@
 
  public:
   ParallelScavengeHeap(GenerationSizer* policy) :
-    CollectedHeap(), _collector_policy(policy), _death_march_count(0) { }
+    CollectedHeap(),
+    _collector_policy(policy),
+    _gens(NULL),
+    _death_march_count(0),
+    _young_manager(NULL),
+    _old_manager(NULL),
+    _eden_pool(NULL),
+    _survivor_pool(NULL),
+    _old_pool(NULL) { }
 
   // For use by VM operations
   enum CollectionType {
@@ -157,13 +165,12 @@
   // collection.
   virtual bool is_maximal_no_gc() const;
 
-  // Return true if the reference points to an object that
-  // can be moved in a partial collection.  For currently implemented
-  // generational collectors that means during a collection of
-  // the young gen.
-  virtual bool is_scavengable(oop obj);
   virtual void register_nmethod(nmethod* nm);
-  virtual void verify_nmethod(nmethod* nmethod);
+  virtual void unregister_nmethod(nmethod* nm);
+  virtual void verify_nmethod(nmethod* nm);
+  virtual void flush_nmethod(nmethod* nm);
+
+  void prune_scavengable_nmethods();
 
   size_t max_capacity() const;
 
--- a/src/hotspot/share/gc/parallel/pcTasks.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/pcTasks.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -117,7 +117,7 @@
 
     case code_cache:
       // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
-      //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
+      //ScavengableNMethods::scavengable_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
       AOTLoader::oops_do(&mark_and_push_closure);
       break;
 
--- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,34 +49,25 @@
                         init_survivor_size,
                         gc_pause_goal_sec,
                         gc_cost_ratio),
+     _avg_major_pause(new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding)),
+     _avg_base_footprint(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
+     _gc_stats(),
      _collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin / 100.0),
+     _major_pause_old_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
+     _major_pause_young_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
      _latest_major_mutator_interval_seconds(0),
      _space_alignment(space_alignment),
      _gc_minor_pause_goal_sec(gc_minor_pause_goal_sec),
      _live_at_last_full_gc(init_promo_size),
-     _young_gen_change_for_major_pause_count(0)
+     _change_old_gen_for_min_pauses(0),
+     _change_young_gen_for_maj_pauses(0),
+     _old_gen_policy_is_ready(false),
+     _young_gen_size_increment_supplement(YoungGenerationSizeSupplement),
+     _old_gen_size_increment_supplement(TenuredGenerationSizeSupplement),
+     _bytes_absorbed_from_eden(0)
 {
-  // Sizing policy statistics
-  _avg_major_pause    =
-    new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
-  _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
-  _avg_major_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
-
-  _avg_base_footprint = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
-  _major_pause_old_estimator =
-    new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
-  _major_pause_young_estimator =
-    new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
-  _major_collection_estimator =
-    new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
-
-  _young_gen_size_increment_supplement = YoungGenerationSizeSupplement;
-  _old_gen_size_increment_supplement = TenuredGenerationSizeSupplement;
-
   // Start the timers
   _major_timer.start();
-
-  _old_gen_policy_is_ready = false;
 }
 
 size_t PSAdaptiveSizePolicy::calculate_free_based_on_live(size_t live, uintx ratio_as_percentage) {
--- a/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -75,7 +75,6 @@
   // Statistical data gathered for GC
   GCStats _gc_stats;
 
-  size_t _survivor_size_limit;   // Limit in bytes of survivor size
   const double _collection_cost_margin_fraction;
 
   // Variable for estimating the major and minor pause times.
@@ -111,13 +110,6 @@
   // Flag indicating that the adaptive policy is ready to use
   bool _old_gen_policy_is_ready;
 
-  // Changing the generation sizing depends on the data that is
-  // gathered about the effects of changes on the pause times and
-  // throughput.  These variable count the number of data points
-  // gathered.  The policy may use these counters as a threshold
-  // for reliable data.
-  julong _young_gen_change_for_major_pause_count;
-
   // To facilitate faster growth at start up, supplement the normal
   // growth percentage for the young gen eden and the
   // old gen space for promotion with these value which decay
--- a/src/hotspot/share/gc/parallel/psCardTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psCardTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -140,19 +140,19 @@
   // It is a waste to get here if empty.
   assert(sp->bottom() < sp->top(), "Should not be called if empty");
   oop* sp_top = (oop*)space_top;
-  jbyte* start_card = byte_for(sp->bottom());
-  jbyte* end_card   = byte_for(sp_top - 1) + 1;
+  CardValue* start_card = byte_for(sp->bottom());
+  CardValue* end_card   = byte_for(sp_top - 1) + 1;
   oop* last_scanned = NULL; // Prevent scanning objects more than once
   // The width of the stripe ssize*stripe_total must be
   // consistent with the number of stripes so that the complete slice
   // is covered.
   size_t slice_width = ssize * stripe_total;
-  for (jbyte* slice = start_card; slice < end_card; slice += slice_width) {
-    jbyte* worker_start_card = slice + stripe_number * ssize;
+  for (CardValue* slice = start_card; slice < end_card; slice += slice_width) {
+    CardValue* worker_start_card = slice + stripe_number * ssize;
     if (worker_start_card >= end_card)
       return; // We're done.
 
-    jbyte* worker_end_card = worker_start_card + ssize;
+    CardValue* worker_end_card = worker_start_card + ssize;
     if (worker_end_card > end_card)
       worker_end_card = end_card;
 
@@ -209,13 +209,13 @@
     assert(worker_start_card <= end_card, "worker start card beyond end card");
     assert(worker_end_card <= end_card, "worker end card beyond end card");
 
-    jbyte* current_card = worker_start_card;
+    CardValue* current_card = worker_start_card;
     while (current_card < worker_end_card) {
       // Find an unclean card.
       while (current_card < worker_end_card && card_is_clean(*current_card)) {
         current_card++;
       }
-      jbyte* first_unclean_card = current_card;
+      CardValue* first_unclean_card = current_card;
 
       // Find the end of a run of contiguous unclean cards
       while (current_card < worker_end_card && !card_is_clean(*current_card)) {
@@ -232,7 +232,7 @@
           HeapWord* last_object_in_dirty_region = start_array->object_start(addr_for(current_card)-1);
           size_t size_of_last_object = oop(last_object_in_dirty_region)->size();
           HeapWord* end_of_last_object = last_object_in_dirty_region + size_of_last_object;
-          jbyte* ending_card_of_last_object = byte_for(end_of_last_object);
+          CardValue* ending_card_of_last_object = byte_for(end_of_last_object);
           assert(ending_card_of_last_object <= worker_end_card, "ending_card_of_last_object is greater than worker_end_card");
           if (ending_card_of_last_object > current_card) {
             // This means the object spans the next complete card.
@@ -241,7 +241,7 @@
           }
         }
       }
-      jbyte* following_clean_card = current_card;
+      CardValue* following_clean_card = current_card;
 
       if (first_unclean_card < worker_end_card) {
         oop* p = (oop*) start_array->object_start(addr_for(first_unclean_card));
@@ -342,8 +342,8 @@
 }
 
 void PSCardTable::verify_all_young_refs_precise_helper(MemRegion mr) {
-  jbyte* bot = byte_for(mr.start());
-  jbyte* top = byte_for(mr.end());
+  CardValue* bot = byte_for(mr.start());
+  CardValue* top = byte_for(mr.end());
   while (bot <= top) {
     assert(*bot == clean_card || *bot == verify_card, "Found unwanted or unknown card mark");
     if (*bot == verify_card)
@@ -353,8 +353,8 @@
 }
 
 bool PSCardTable::addr_is_marked_imprecise(void *addr) {
-  jbyte* p = byte_for(addr);
-  jbyte val = *p;
+  CardValue* p = byte_for(addr);
+  CardValue val = *p;
 
   if (card_is_dirty(val))
     return true;
@@ -372,8 +372,8 @@
 
 // Also includes verify_card
 bool PSCardTable::addr_is_marked_precise(void *addr) {
-  jbyte* p = byte_for(addr);
-  jbyte val = *p;
+  CardValue* p = byte_for(addr);
+  CardValue val = *p;
 
   if (card_is_newgen(val))
     return true;
@@ -473,7 +473,7 @@
   log_trace(gc, barrier)("    byte_for(start): " INTPTR_FORMAT "  byte_for(last): " INTPTR_FORMAT,
                 p2i(byte_for(_covered[ind].start())),  p2i(byte_for(_covered[ind].last())));
   log_trace(gc, barrier)("    addr_for(start): " INTPTR_FORMAT "  addr_for(last): " INTPTR_FORMAT,
-                p2i(addr_for((jbyte*) _committed[ind].start())), p2i(addr_for((jbyte*) _committed[ind].last())));
+                p2i(addr_for((CardValue*) _committed[ind].start())), p2i(addr_for((CardValue*) _committed[ind].last())));
 
   debug_only(verify_guard();)
 }
@@ -503,7 +503,7 @@
          "Starts should have proper alignment");
 #endif
 
-  jbyte* new_start = byte_for(new_region.start());
+  CardValue* new_start = byte_for(new_region.start());
   // Round down because this is for the start address
   HeapWord* new_start_aligned = align_down((HeapWord*)new_start, os::vm_page_size());
   // The guard page is always committed and should not be committed over.
@@ -575,7 +575,7 @@
 void PSCardTable::resize_update_committed_table(int changed_region,
                                                 MemRegion new_region) {
 
-  jbyte* new_start = byte_for(new_region.start());
+  CardValue* new_start = byte_for(new_region.start());
   // Set the new start of the committed region
   HeapWord* new_start_aligned = align_down((HeapWord*)new_start, os::vm_page_size());
   MemRegion new_committed = MemRegion(new_start_aligned,
@@ -590,13 +590,13 @@
   MemRegion original_covered = _covered[changed_region];
   // Initialize the card entries.  Only consider the
   // region covered by the card table (_whole_heap)
-  jbyte* entry;
+  CardValue* entry;
   if (new_region.start() < _whole_heap.start()) {
     entry = byte_for(_whole_heap.start());
   } else {
     entry = byte_for(new_region.start());
   }
-  jbyte* end = byte_for(original_covered.start());
+  CardValue* end = byte_for(original_covered.start());
   // If _whole_heap starts at the original covered regions start,
   // this loop will not execute.
   while (entry < end) { *entry++ = clean_card; }
--- a/src/hotspot/share/gc/parallel/psCardTable.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psCardTable.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -54,8 +54,8 @@
  public:
   PSCardTable(MemRegion whole_heap) : CardTable(whole_heap, /* scanned_concurrently */ false) {}
 
-  static jbyte youngergen_card_val() { return youngergen_card; }
-  static jbyte verify_card_val()     { return verify_card; }
+  static CardValue youngergen_card_val() { return youngergen_card; }
+  static CardValue verify_card_val()     { return verify_card; }
 
   // Scavenge support
   void scavenge_contents_parallel(ObjectStartArray* start_array,
@@ -68,7 +68,7 @@
   bool addr_is_marked_imprecise(void *addr);
   bool addr_is_marked_precise(void *addr);
 
-  void set_card_newgen(void* addr)   { jbyte* p = byte_for(addr); *p = verify_card; }
+  void set_card_newgen(void* addr)   { CardValue* p = byte_for(addr); *p = verify_card; }
 
   // Testers for entries
   static bool card_is_dirty(int value)      { return value == dirty_card; }
@@ -78,7 +78,7 @@
 
   // Card marking
   void inline_write_ref_field_gc(void* field, oop new_val) {
-    jbyte* byte = byte_for(field);
+    CardValue* byte = byte_for(field);
     *byte = youngergen_card;
   }
 
@@ -99,7 +99,7 @@
   HeapWord* lowest_prev_committed_start(int ind) const;
 
 #ifdef ASSERT
-  bool is_valid_card_address(jbyte* addr) {
+  bool is_valid_card_address(CardValue* addr) {
     return (addr >= _byte_map) && (addr < _byte_map + _byte_map_size);
   }
 #endif // ASSERT
--- a/src/hotspot/share/gc/parallel/psFileBackedVirtualspace.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psFileBackedVirtualspace.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,10 +51,6 @@
   return true;
 }
 
-PSFileBackedVirtualSpace::PSFileBackedVirtualSpace(ReservedSpace rs, const char* path) {
-  PSFileBackedVirtualSpace(rs, os::vm_page_size(), path);
-}
-
 bool PSFileBackedVirtualSpace::expand_by(size_t bytes) {
   assert(special(), "Since entire space is committed at initialization, _special should always be true for PSFileBackedVirtualSpace");
 
--- a/src/hotspot/share/gc/parallel/psFileBackedVirtualspace.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psFileBackedVirtualspace.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -34,7 +34,6 @@
   bool _mapping_succeeded;
 public:
   PSFileBackedVirtualSpace(ReservedSpace rs, size_t alignment, const char* file_path);
-  PSFileBackedVirtualSpace(ReservedSpace rs, const char* file_path);
 
   bool   initialize();
   bool   expand_by(size_t bytes);
--- a/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psMarkSweep.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -187,7 +187,6 @@
     // Let the size policy know we're starting
     size_policy->major_collection_begin();
 
-    CodeCache::gc_prologue();
     BiasedLocking::preserve_marks();
 
     // Capture metadata size before collection for sizing.
@@ -255,7 +254,7 @@
     MetaspaceUtils::verify_metrics();
 
     BiasedLocking::restore_marks();
-    CodeCache::gc_epilogue();
+    heap->prune_scavengable_nmethods();
     JvmtiExport::gc_epilogue();
 
 #if COMPILER2_OR_JVMCI
@@ -524,7 +523,7 @@
     SystemDictionary::oops_do(mark_and_push_closure());
     ClassLoaderDataGraph::always_strong_cld_do(follow_cld_closure());
     // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
-    //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
+    //ScavengableNMethods::scavengable_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
     AOTLoader::oops_do(mark_and_push_closure());
   }
 
--- a/src/hotspot/share/gc/parallel/psMarkSweepDecorator.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psMarkSweepDecorator.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -52,7 +52,11 @@
  public:
   PSMarkSweepDecorator(MutableSpace* space, ObjectStartArray* start_array,
                        size_t allowed_dead_ratio) :
-    _space(space), _start_array(start_array),
+    _space(space),
+    _start_array(start_array),
+    _first_dead(NULL),
+    _end_of_live(NULL),
+    _compaction_top(NULL),
     _allowed_dead_ratio(allowed_dead_ratio) { }
 
   // During a compacting collection, we need to collapse objects into
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -406,19 +406,16 @@
 size_t mark_bitmap_size;
 #endif  // #ifdef ASSERT
 
-ParallelCompactData::ParallelCompactData()
-{
-  _region_start = 0;
-
-  _region_vspace = 0;
-  _reserved_byte_size = 0;
-  _region_data = 0;
-  _region_count = 0;
-
-  _block_vspace = 0;
-  _block_data = 0;
-  _block_count = 0;
-}
+ParallelCompactData::ParallelCompactData() :
+  _region_start(NULL),
+  DEBUG_ONLY(_region_end(NULL) COMMA)
+  _region_vspace(NULL),
+  _reserved_byte_size(0),
+  _region_data(NULL),
+  _region_count(0),
+  _block_vspace(NULL),
+  _block_data(NULL),
+  _block_count(0) {}
 
 bool ParallelCompactData::initialize(MemRegion covered_region)
 {
@@ -1061,7 +1058,7 @@
   ClassLoaderDataGraph::purge();
   MetaspaceUtils::verify_metrics();
 
-  CodeCache::gc_epilogue();
+  heap->prune_scavengable_nmethods();
   JvmtiExport::gc_epilogue();
 
 #if COMPILER2_OR_JVMCI
@@ -1807,8 +1804,6 @@
     // Let the size policy know we're starting
     size_policy->major_collection_begin();
 
-    CodeCache::gc_prologue();
-
 #if COMPILER2_OR_JVMCI
     DerivedPointerTable::clear();
 #endif
--- a/src/hotspot/share/gc/parallel/psTasks.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psTasks.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -28,12 +28,14 @@
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/parallel/gcTaskManager.hpp"
+#include "gc/parallel/parallelScavengeHeap.inline.hpp"
 #include "gc/parallel/psCardTable.hpp"
 #include "gc/parallel/psClosure.inline.hpp"
 #include "gc/parallel/psPromotionManager.hpp"
 #include "gc/parallel/psPromotionManager.inline.hpp"
 #include "gc/parallel/psScavenge.inline.hpp"
 #include "gc/parallel/psTasks.hpp"
+#include "gc/shared/scavengableNMethods.hpp"
 #include "gc/shared/taskqueue.inline.hpp"
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
@@ -96,8 +98,8 @@
 
     case code_cache:
       {
-        MarkingCodeBlobClosure each_scavengable_code_blob(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
-        CodeCache::scavenge_root_nmethods_do(&each_scavengable_code_blob);
+        MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
+        ScavengableNMethods::nmethods_do(&code_closure);
         AOTLoader::oops_do(&roots_closure);
       }
       break;
--- a/src/hotspot/share/gc/parallel/psVirtualspace.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psVirtualspace.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,13 @@
 }
 
 // Deprecated.
-PSVirtualSpace::PSVirtualSpace(): _alignment(os::vm_page_size()) {
+PSVirtualSpace::PSVirtualSpace():
+  _alignment(os::vm_page_size()),
+  _reserved_low_addr(NULL),
+  _reserved_high_addr(NULL),
+  _committed_low_addr(NULL),
+  _committed_high_addr(NULL),
+  _special(false) {
 }
 
 // Deprecated.
--- a/src/hotspot/share/gc/parallel/psVirtualspace.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psVirtualspace.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -64,7 +64,14 @@
   // Eventually all instances should be created with the above 1- or 2-arg
   // constructors.  Then the 1st constructor below should become protected and
   // the 2nd ctor and initialize() removed.
-  PSVirtualSpace(size_t alignment): _alignment(alignment) { }
+  PSVirtualSpace(size_t alignment):
+    _alignment(alignment),
+    _reserved_low_addr(NULL),
+    _reserved_high_addr(NULL),
+    _committed_low_addr(NULL),
+    _committed_high_addr(NULL),
+    _special(false) {
+  }
   PSVirtualSpace();
   bool initialize(ReservedSpace rs, size_t commit_size);
 
--- a/src/hotspot/share/gc/parallel/psYoungGen.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/parallel/psYoungGen.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,12 +35,22 @@
 #include "runtime/java.hpp"
 #include "utilities/align.hpp"
 
-PSYoungGen::PSYoungGen(size_t        initial_size,
-                       size_t        min_size,
-                       size_t        max_size) :
+PSYoungGen::PSYoungGen(size_t initial_size, size_t min_size, size_t max_size) :
+  _reserved(),
+  _virtual_space(NULL),
+  _eden_space(NULL),
+  _from_space(NULL),
+  _to_space(NULL),
+  _eden_mark_sweep(NULL),
+  _from_mark_sweep(NULL),
+  _to_mark_sweep(NULL),
   _init_gen_size(initial_size),
   _min_gen_size(min_size),
-  _max_gen_size(max_size)
+  _max_gen_size(max_size),
+  _gen_counters(NULL),
+  _eden_counters(NULL),
+  _from_counters(NULL),
+  _to_counters(NULL)
 {}
 
 void PSYoungGen::initialize_virtual_space(ReservedSpace rs, size_t alignment) {
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -75,10 +75,6 @@
 
   gch->trace_heap_before_gc(_gc_tracer);
 
-  // When collecting the permanent generation Method*s may be moving,
-  // so we either have to flush all bcp data or convert it into bci.
-  CodeCache::gc_prologue();
-
   // Increment the invocation count
   _total_invocations++;
 
@@ -128,7 +124,7 @@
     rs->invalidate_or_clear(old_gen);
   }
 
-  CodeCache::gc_epilogue();
+  gch->prune_scavengable_nmethods();
   JvmtiExport::gc_epilogue();
 
   // refs processing: clean slate
--- a/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -48,40 +48,38 @@
     _eden_size(init_eden_size),
     _promo_size(init_promo_size),
     _survivor_size(init_survivor_size),
+    _avg_minor_pause(new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding)),
+    _avg_minor_interval(new AdaptiveWeightedAverage(AdaptiveTimeWeight)),
+    _avg_minor_gc_cost(new AdaptiveWeightedAverage(AdaptiveTimeWeight)),
+    _avg_major_interval(new AdaptiveWeightedAverage(AdaptiveTimeWeight)),
+    _avg_major_gc_cost(new AdaptiveWeightedAverage(AdaptiveTimeWeight)),
+    _avg_young_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
+    _avg_eden_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
+    _avg_old_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
+    _avg_survived(new AdaptivePaddedAverage(AdaptiveSizePolicyWeight, SurvivorPadding)),
+    _avg_pretenured(new AdaptivePaddedNoZeroDevAverage(AdaptiveSizePolicyWeight, SurvivorPadding)),
+    _minor_pause_old_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
+    _minor_pause_young_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
+    _minor_collection_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
+    _major_collection_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
     _latest_minor_mutator_interval_seconds(0),
     _threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0),
     _gc_pause_goal_sec(gc_pause_goal_sec),
+    _young_gen_policy_is_ready(false),
+    _change_young_gen_for_min_pauses(0),
+    _change_old_gen_for_maj_pauses(0),
+    _change_old_gen_for_throughput(0),
+    _change_young_gen_for_throughput(0),
+    _increment_tenuring_threshold_for_gc_cost(false),
+    _decrement_tenuring_threshold_for_gc_cost(false),
+    _decrement_tenuring_threshold_for_survivor_limit(false),
+    _decrease_for_footprint(0),
+    _decide_at_full_gc(0),
     _young_gen_change_for_minor_throughput(0),
     _old_gen_change_for_major_throughput(0) {
-  _avg_minor_pause    =
-    new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
-  _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
-  _avg_minor_gc_cost  = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
-  _avg_major_gc_cost  = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
-
-  _avg_young_live     = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
-  _avg_old_live       = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
-  _avg_eden_live      = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
-
-  _avg_survived       = new AdaptivePaddedAverage(AdaptiveSizePolicyWeight,
-                                                  SurvivorPadding);
-  _avg_pretenured     = new AdaptivePaddedNoZeroDevAverage(
-                                                  AdaptiveSizePolicyWeight,
-                                                  SurvivorPadding);
-
-  _minor_pause_old_estimator =
-    new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
-  _minor_pause_young_estimator =
-    new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
-  _minor_collection_estimator =
-    new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
-  _major_collection_estimator =
-    new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
 
   // Start the timers
   _minor_timer.start();
-
-  _young_gen_policy_is_ready = false;
 }
 
 bool AdaptiveSizePolicy::tenuring_threshold_change() const {
--- a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -45,7 +45,6 @@
   BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
-  assert(sizeof(*(ct->byte_map_base())) == sizeof(jbyte), "adjust this code");
   LIR_Const* card_table_base = new LIR_Const(ct->byte_map_base());
   if (addr->is_address()) {
     LIR_Address* address = addr->as_address_ptr();
--- a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -37,7 +37,7 @@
 
 Node* CardTableBarrierSetC2::byte_map_base_node(GraphKit* kit) const {
   // Get base of card map
-  jbyte* card_table_base = ci_card_table_address();
+  CardTable::CardValue* card_table_base = ci_card_table_address();
    if (card_table_base != NULL) {
      return kit->makecon(TypeRawPtr::make((address)card_table_base));
    } else {
--- a/src/hotspot/share/gc/shared/cardTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/cardTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -109,12 +109,12 @@
   // then add it to _byte_map_base, i.e.
   //
   //   _byte_map = _byte_map_base + (uintptr_t(low_bound) >> card_shift)
-  _byte_map = (jbyte*) heap_rs.base();
+  _byte_map = (CardValue*) heap_rs.base();
   _byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
   assert(byte_for(low_bound) == &_byte_map[0], "Checking start of map");
   assert(byte_for(high_bound-1) <= &_byte_map[_last_valid_index], "Checking end of map");
 
-  jbyte* guard_card = &_byte_map[_guard_index];
+  CardValue* guard_card = &_byte_map[_guard_index];
   HeapWord* guard_page = align_down((HeapWord*)guard_card, _page_size);
   _guard_region = MemRegion(guard_page, _page_size);
   os::commit_memory_or_exit((char*)guard_page, _page_size, _page_size,
@@ -145,7 +145,7 @@
   _cur_covered_regions++;
   _covered[res].set_start(base);
   _covered[res].set_word_size(0);
-  jbyte* ct_start = byte_for(base);
+  CardValue* ct_start = byte_for(base);
   HeapWord* ct_start_aligned = align_down((HeapWord*)ct_start, _page_size);
   _committed[res].set_start(ct_start_aligned);
   _committed[res].set_word_size(0);
@@ -302,7 +302,7 @@
 #endif
 
     // The default of 0 is not necessarily clean cards.
-    jbyte* entry;
+    CardValue* entry;
     if (old_region.last() < _whole_heap.start()) {
       entry = byte_for(_whole_heap.start());
     } else {
@@ -312,8 +312,8 @@
       "The guard card will be overwritten");
     // This line commented out cleans the newly expanded region and
     // not the aligned up expanded region.
-    // jbyte* const end = byte_after(new_region.last());
-    jbyte* const end = (jbyte*) new_end_for_commit;
+    // CardValue* const end = byte_after(new_region.last());
+    CardValue* const end = (CardValue*) new_end_for_commit;
     assert((end >= byte_after(new_region.last())) || collided || guarded,
       "Expect to be beyond new region unless impacting another region");
     // do nothing if we resized downward.
@@ -330,7 +330,7 @@
     }
 #endif
     if (entry < end) {
-      memset(entry, clean_card, pointer_delta(end, entry, sizeof(jbyte)));
+      memset(entry, clean_card, pointer_delta(end, entry, sizeof(CardValue)));
     }
   }
   // In any case, the covered size changes.
@@ -344,7 +344,7 @@
   log_trace(gc, barrier)("    byte_for(start): " INTPTR_FORMAT "  byte_for(last): " INTPTR_FORMAT,
                          p2i(byte_for(_covered[ind].start())),  p2i(byte_for(_covered[ind].last())));
   log_trace(gc, barrier)("    addr_for(start): " INTPTR_FORMAT "  addr_for(last): " INTPTR_FORMAT,
-                         p2i(addr_for((jbyte*) _committed[ind].start())),  p2i(addr_for((jbyte*) _committed[ind].last())));
+                         p2i(addr_for((CardValue*) _committed[ind].start())),  p2i(addr_for((CardValue*) _committed[ind].last())));
 
   // Touch the last card of the covered region to show that it
   // is committed (or SEGV).
@@ -357,8 +357,8 @@
 void CardTable::dirty_MemRegion(MemRegion mr) {
   assert(align_down(mr.start(), HeapWordSize) == mr.start(), "Unaligned start");
   assert(align_up  (mr.end(),   HeapWordSize) == mr.end(),   "Unaligned end"  );
-  jbyte* cur  = byte_for(mr.start());
-  jbyte* last = byte_after(mr.last());
+  CardValue* cur  = byte_for(mr.start());
+  CardValue* last = byte_after(mr.last());
   while (cur < last) {
     *cur = dirty_card;
     cur++;
@@ -368,15 +368,15 @@
 void CardTable::clear_MemRegion(MemRegion mr) {
   // Be conservative: only clean cards entirely contained within the
   // region.
-  jbyte* cur;
+  CardValue* cur;
   if (mr.start() == _whole_heap.start()) {
     cur = byte_for(mr.start());
   } else {
     assert(mr.start() > _whole_heap.start(), "mr is not covered.");
     cur = byte_after(mr.start() - 1);
   }
-  jbyte* last = byte_after(mr.last());
-  memset(cur, clean_card, pointer_delta(last, cur, sizeof(jbyte)));
+  CardValue* last = byte_after(mr.last());
+  memset(cur, clean_card, pointer_delta(last, cur, sizeof(CardValue)));
 }
 
 void CardTable::clear(MemRegion mr) {
@@ -387,8 +387,8 @@
 }
 
 void CardTable::dirty(MemRegion mr) {
-  jbyte* first = byte_for(mr.start());
-  jbyte* last  = byte_after(mr.last());
+  CardValue* first = byte_for(mr.start());
+  CardValue* last  = byte_after(mr.last());
   memset(first, dirty_card, last-first);
 }
 
@@ -398,7 +398,7 @@
   for (int i = 0; i < _cur_covered_regions; i++) {
     MemRegion mri = mr.intersection(_covered[i]);
     if (!mri.is_empty()) {
-      jbyte *cur_entry, *next_entry, *limit;
+      CardValue *cur_entry, *next_entry, *limit;
       for (cur_entry = byte_for(mri.start()), limit = byte_for(mri.last());
            cur_entry <= limit;
            cur_entry  = next_entry) {
@@ -424,7 +424,7 @@
   for (int i = 0; i < _cur_covered_regions; i++) {
     MemRegion mri = mr.intersection(_covered[i]);
     if (!mri.is_empty()) {
-      jbyte* cur_entry, *next_entry, *limit;
+      CardValue* cur_entry, *next_entry, *limit;
       for (cur_entry = byte_for(mri.start()), limit = byte_for(mri.last());
            cur_entry <= limit;
            cur_entry  = next_entry) {
@@ -474,13 +474,12 @@
 }
 
 #ifndef PRODUCT
-void CardTable::verify_region(MemRegion mr,
-                                      jbyte val, bool val_equals) {
-  jbyte* start    = byte_for(mr.start());
-  jbyte* end      = byte_for(mr.last());
+void CardTable::verify_region(MemRegion mr, CardValue val, bool val_equals) {
+  CardValue* start    = byte_for(mr.start());
+  CardValue* end      = byte_for(mr.last());
   bool failures = false;
-  for (jbyte* curr = start; curr <= end; ++curr) {
-    jbyte curr_val = *curr;
+  for (CardValue* curr = start; curr <= end; ++curr) {
+    CardValue curr_val = *curr;
     bool failed = (val_equals) ? (curr_val != val) : (curr_val == val);
     if (failed) {
       if (!failures) {
--- a/src/hotspot/share/gc/shared/cardTable.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/cardTable.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -32,6 +32,14 @@
 
 class CardTable: public CHeapObj<mtGC> {
   friend class VMStructs;
+public:
+  typedef uint8_t CardValue;
+
+  // All code generators assume that the size of a card table entry is one byte.
+  // They need to be updated to reflect any change to this.
+  // This code can typically be found by searching for the byte_map_base() method.
+  STATIC_ASSERT(sizeof(CardValue) == 1);
+
 protected:
   // The declaration order of these const fields is important; see the
   // constructor before changing.
@@ -43,8 +51,8 @@
   size_t          _last_valid_index; // index of the last valid element
   const size_t    _page_size;        // page size used when mapping _byte_map
   size_t          _byte_map_size;    // in bytes
-  jbyte*          _byte_map;         // the card marking array
-  jbyte*          _byte_map_base;
+  CardValue*      _byte_map;         // the card marking array
+  CardValue*      _byte_map_base;
 
   int _cur_covered_regions;
 
@@ -94,7 +102,7 @@
   static const int _max_covered_regions = 2;
 
   enum CardValues {
-    clean_card                  = -1,
+    clean_card                  = (CardValue)-1,
     // The mask contains zeros in places for all other values.
     clean_card_mask             = clean_card - 31,
 
@@ -145,17 +153,17 @@
 
   // Return true if "p" is at the start of a card.
   bool is_card_aligned(HeapWord* p) {
-    jbyte* pcard = byte_for(p);
+    CardValue* pcard = byte_for(p);
     return (addr_for(pcard) == p);
   }
 
   // Mapping from address to card marking array entry
-  jbyte* byte_for(const void* p) const {
+  CardValue* byte_for(const void* p) const {
     assert(_whole_heap.contains(p),
            "Attempt to access p = " PTR_FORMAT " out of bounds of "
            " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")",
            p2i(p), p2i(_whole_heap.start()), p2i(_whole_heap.end()));
-    jbyte* result = &_byte_map_base[uintptr_t(p) >> card_shift];
+    CardValue* result = &_byte_map_base[uintptr_t(p) >> card_shift];
     assert(result >= _byte_map && result < _byte_map + _byte_map_size,
            "out of bounds accessor for card marking array");
     return result;
@@ -164,7 +172,7 @@
   // The card table byte one after the card marking array
   // entry for argument address. Typically used for higher bounds
   // for loops iterating through the card table.
-  jbyte* byte_after(const void* p) const {
+  CardValue* byte_after(const void* p) const {
     return byte_for(p) + 1;
   }
 
@@ -173,20 +181,20 @@
   void dirty(MemRegion mr);
 
   // Provide read-only access to the card table array.
-  const jbyte* byte_for_const(const void* p) const {
+  const CardValue* byte_for_const(const void* p) const {
     return byte_for(p);
   }
-  const jbyte* byte_after_const(const void* p) const {
+  const CardValue* byte_after_const(const void* p) const {
     return byte_after(p);
   }
 
   // Mapping from card marking array entry to address of first word
-  HeapWord* addr_for(const jbyte* p) const {
+  HeapWord* addr_for(const CardValue* p) const {
     assert(p >= _byte_map && p < _byte_map + _byte_map_size,
            "out of bounds access to card marking array. p: " PTR_FORMAT
            " _byte_map: " PTR_FORMAT " _byte_map + _byte_map_size: " PTR_FORMAT,
            p2i(p), p2i(_byte_map), p2i(_byte_map + _byte_map_size));
-    size_t delta = pointer_delta(p, _byte_map_base, sizeof(jbyte));
+    size_t delta = pointer_delta(p, _byte_map_base, sizeof(CardValue));
     HeapWord* result = (HeapWord*) (delta << card_shift);
     assert(_whole_heap.contains(result),
            "Returning result = " PTR_FORMAT " out of bounds of "
@@ -204,7 +212,7 @@
     return byte_for(p) - _byte_map;
   }
 
-  const jbyte* byte_for_index(const size_t card_index) const {
+  CardValue* byte_for_index(const size_t card_index) const {
     return _byte_map + card_index;
   }
 
@@ -233,19 +241,19 @@
     card_size_in_words          = card_size / sizeof(HeapWord)
   };
 
-  static jbyte clean_card_val()          { return clean_card; }
-  static jbyte clean_card_mask_val()     { return clean_card_mask; }
-  static jbyte dirty_card_val()          { return dirty_card; }
-  static jbyte claimed_card_val()        { return claimed_card; }
-  static jbyte precleaned_card_val()     { return precleaned_card; }
-  static jbyte deferred_card_val()       { return deferred_card; }
+  static CardValue clean_card_val()          { return clean_card; }
+  static CardValue clean_card_mask_val()     { return clean_card_mask; }
+  static CardValue dirty_card_val()          { return dirty_card; }
+  static CardValue claimed_card_val()        { return claimed_card; }
+  static CardValue precleaned_card_val()     { return precleaned_card; }
+  static CardValue deferred_card_val()       { return deferred_card; }
   static intptr_t clean_card_row_val()   { return clean_card_row; }
 
   // Card marking array base (adjusted for heap low boundary)
   // This would be the 0th element of _byte_map, if the heap started at 0x0.
   // But since the heap starts at some higher address, this points to somewhere
   // before the beginning of the actual _byte_map.
-  jbyte* byte_map_base() const { return _byte_map_base; }
+  CardValue* byte_map_base() const { return _byte_map_base; }
   bool scanned_concurrently() const { return _scanned_concurrently; }
 
   virtual bool is_in_young(oop obj) const = 0;
@@ -258,7 +266,7 @@
 
   // val_equals -> it will check that all cards covered by mr equal val
   // !val_equals -> it will check that all cards covered by mr do not equal val
-  void verify_region(MemRegion mr, jbyte val, bool val_equals) PRODUCT_RETURN;
+  void verify_region(MemRegion mr, CardValue val, bool val_equals) PRODUCT_RETURN;
   void verify_not_dirty_region(MemRegion mr) PRODUCT_RETURN;
   void verify_dirty_region(MemRegion mr) PRODUCT_RETURN;
 };
--- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSetAssembler.hpp"
 #include "gc/shared/cardTableBarrierSet.inline.hpp"
 #include "gc/shared/collectedHeap.hpp"
--- a/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -25,11 +25,10 @@
 #ifndef SHARE_GC_SHARED_CARDTABLEBARRIERSET_HPP
 #define SHARE_GC_SHARED_CARDTABLEBARRIERSET_HPP
 
+#include "gc/shared/cardTable.hpp"
 #include "gc/shared/modRefBarrierSet.hpp"
 #include "utilities/align.hpp"
 
-class CardTable;
-
 // This kind of "BarrierSet" allows a "CollectedHeap" to detect and
 // enumerate ref fields that have been modified (since the last
 // enumeration.)
@@ -45,8 +44,11 @@
 class CardTableBarrierSet: public ModRefBarrierSet {
   // Some classes get to look at some private stuff.
   friend class VMStructs;
- protected:
+
+public:
 
+  typedef CardTable::CardValue CardValue;
+protected:
   // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2
   // or INCLUDE_JVMCI is being used
   bool       _defer_initial_card_mark;
--- a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -31,7 +31,7 @@
 
 template <DecoratorSet decorators, typename T>
 inline void CardTableBarrierSet::write_ref_field_post(T* field, oop newVal) {
-  volatile jbyte* byte = _card_table->byte_for(field);
+  volatile CardValue* byte = _card_table->byte_for(field);
   if (_card_table->scanned_concurrently()) {
     // Perform a releasing store if the card table is scanned concurrently
     OrderAccess::release_store(byte, CardTable::dirty_card_val());
--- a/src/hotspot/share/gc/shared/cardTableRS.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/cardTableRS.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -78,9 +78,8 @@
   ClassLoaderDataGraph::cld_do(&closure);
 }
 
-
-jbyte CardTableRS::find_unused_youngergenP_card_value() {
-  for (jbyte v = youngergenP1_card;
+CardTable::CardValue CardTableRS::find_unused_youngergenP_card_value() {
+  for (CardValue v = youngergenP1_card;
        v < cur_youngergen_and_prev_nonclean_card;
        v++) {
     bool seen = false;
@@ -122,7 +121,7 @@
   g->younger_refs_iterate(blk, n_threads);
 }
 
-inline bool ClearNoncleanCardWrapper::clear_card(jbyte* entry) {
+inline bool ClearNoncleanCardWrapper::clear_card(CardValue* entry) {
   if (_is_par) {
     return clear_card_parallel(entry);
   } else {
@@ -130,16 +129,16 @@
   }
 }
 
-inline bool ClearNoncleanCardWrapper::clear_card_parallel(jbyte* entry) {
+inline bool ClearNoncleanCardWrapper::clear_card_parallel(CardValue* entry) {
   while (true) {
     // In the parallel case, we may have to do this several times.
-    jbyte entry_val = *entry;
+    CardValue entry_val = *entry;
     assert(entry_val != CardTableRS::clean_card_val(),
            "We shouldn't be looking at clean cards, and this should "
            "be the only place they get cleaned.");
     if (CardTableRS::card_is_dirty_wrt_gen_iter(entry_val)
         || _ct->is_prev_youngergen_card_val(entry_val)) {
-      jbyte res =
+      CardValue res =
         Atomic::cmpxchg(CardTableRS::clean_card_val(), entry, entry_val);
       if (res == entry_val) {
         break;
@@ -167,8 +166,8 @@
 }
 
 
-inline bool ClearNoncleanCardWrapper::clear_card_serial(jbyte* entry) {
-  jbyte entry_val = *entry;
+inline bool ClearNoncleanCardWrapper::clear_card_serial(CardValue* entry) {
+  CardValue entry_val = *entry;
   assert(entry_val != CardTableRS::clean_card_val(),
          "We shouldn't be looking at clean cards, and this should "
          "be the only place they get cleaned.");
@@ -183,7 +182,7 @@
     _dirty_card_closure(dirty_card_closure), _ct(ct), _is_par(is_par) {
 }
 
-bool ClearNoncleanCardWrapper::is_word_aligned(jbyte* entry) {
+bool ClearNoncleanCardWrapper::is_word_aligned(CardTable::CardValue* entry) {
   return (((intptr_t)entry) & (BytesPerWord-1)) == 0;
 }
 
@@ -195,8 +194,8 @@
   assert(mr.word_size() > 0, "Error");
   assert(_ct->is_aligned(mr.start()), "mr.start() should be card aligned");
   // mr.end() may not necessarily be card aligned.
-  jbyte* cur_entry = _ct->byte_for(mr.last());
-  const jbyte* limit = _ct->byte_for(mr.start());
+  CardValue* cur_entry = _ct->byte_for(mr.last());
+  const CardValue* limit = _ct->byte_for(mr.start());
   HeapWord* end_of_non_clean = mr.end();
   HeapWord* start_of_non_clean = end_of_non_clean;
   while (cur_entry >= limit) {
@@ -215,7 +214,7 @@
 
       // fast forward through potential continuous whole-word range of clean cards beginning at a word-boundary
       if (is_word_aligned(cur_entry)) {
-        jbyte* cur_row = cur_entry - BytesPerWord;
+        CardValue* cur_row = cur_entry - BytesPerWord;
         while (cur_row >= limit && *((intptr_t*)cur_row) ==  CardTableRS::clean_card_row_val()) {
           cur_row -= BytesPerWord;
         }
@@ -252,9 +251,9 @@
 // cur-younger-gen                ==> cur_younger_gen
 // cur_youngergen_and_prev_nonclean_card ==> no change.
 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
-  volatile jbyte* entry = byte_for(field);
+  volatile CardValue* entry = byte_for(field);
   do {
-    jbyte entry_val = *entry;
+    CardValue entry_val = *entry;
     // We put this first because it's probably the most common case.
     if (entry_val == clean_card_val()) {
       // No threat of contention with cleaning threads.
@@ -264,8 +263,8 @@
                || is_prev_youngergen_card_val(entry_val)) {
       // Mark it as both cur and prev youngergen; card cleaning thread will
       // eventually remove the previous stuff.
-      jbyte new_val = cur_youngergen_and_prev_nonclean_card;
-      jbyte res = Atomic::cmpxchg(new_val, entry, entry_val);
+      CardValue new_val = cur_youngergen_and_prev_nonclean_card;
+      CardValue res = Atomic::cmpxchg(new_val, entry, entry_val);
       // Did the CAS succeed?
       if (res == entry_val) return;
       // Otherwise, retry, to see the new value.
@@ -395,11 +394,11 @@
   if (s->end() <= gen_boundary) return;
   MemRegion used = s->used_region();
 
-  jbyte* cur_entry = byte_for(used.start());
-  jbyte* limit = byte_after(used.last());
+  CardValue* cur_entry = byte_for(used.start());
+  CardValue* limit = byte_after(used.last());
   while (cur_entry < limit) {
     if (*cur_entry == clean_card_val()) {
-      jbyte* first_dirty = cur_entry+1;
+      CardValue* first_dirty = cur_entry+1;
       while (first_dirty < limit &&
              *first_dirty == clean_card_val()) {
         first_dirty++;
@@ -614,7 +613,7 @@
   // max_gens is really GenCollectedHeap::heap()->gen_policy()->number_of_generations()
   // (which is always 2, young & old), but GenCollectedHeap has not been initialized yet.
   uint max_gens = 2;
-  _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(jbyte, max_gens + 1,
+  _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(CardValue, max_gens + 1,
                          mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL);
   if (_last_cur_val_in_gen == NULL) {
     vm_exit_during_initialization("Could not create last_cur_val_in_gen array.");
@@ -626,7 +625,7 @@
 
 CardTableRS::~CardTableRS() {
   if (_last_cur_val_in_gen) {
-    FREE_C_HEAP_ARRAY(jbyte, _last_cur_val_in_gen);
+    FREE_C_HEAP_ARRAY(CardValue, _last_cur_val_in_gen);
     _last_cur_val_in_gen = NULL;
   }
   if (_lowest_non_clean) {
@@ -669,11 +668,11 @@
   }
 }
 
-bool CardTableRS::card_will_be_scanned(jbyte cv) {
+bool CardTableRS::card_will_be_scanned(CardValue cv) {
   return card_is_dirty_wrt_gen_iter(cv) || is_prev_nonclean_card_val(cv);
 }
 
-bool CardTableRS::card_may_have_been_dirty(jbyte cv) {
+bool CardTableRS::card_may_have_been_dirty(CardValue cv) {
   return
     cv != clean_card &&
     (card_is_dirty_wrt_gen_iter(cv) ||
--- a/src/hotspot/share/gc/shared/cardTableRS.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/cardTableRS.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -76,27 +76,27 @@
   // used as the current value for a younger_refs_do iteration of that
   // portion of the table. The perm gen is index 0. The young gen is index 1,
   // but will always have the value "clean_card". The old gen is index 2.
-  jbyte* _last_cur_val_in_gen;
+  CardValue* _last_cur_val_in_gen;
 
-  jbyte _cur_youngergen_card_val;
+  CardValue _cur_youngergen_card_val;
 
   // Number of generations, plus one for lingering PermGen issues in CardTableRS.
   static const int _regions_to_iterate = 3;
 
-  jbyte cur_youngergen_card_val() {
+  CardValue cur_youngergen_card_val() {
     return _cur_youngergen_card_val;
   }
-  void set_cur_youngergen_card_val(jbyte v) {
+  void set_cur_youngergen_card_val(CardValue v) {
     _cur_youngergen_card_val = v;
   }
-  bool is_prev_youngergen_card_val(jbyte v) {
+  bool is_prev_youngergen_card_val(CardValue v) {
     return
       youngergen_card <= v &&
       v < cur_youngergen_and_prev_nonclean_card &&
       v != _cur_youngergen_card_val;
   }
   // Return a youngergen_card_value that is not currently in use.
-  jbyte find_unused_youngergenP_card_value();
+  CardValue find_unused_youngergenP_card_value();
 
 public:
   CardTableRS(MemRegion whole_heap, bool scanned_concurrently);
@@ -117,7 +117,7 @@
   void younger_refs_iterate(Generation* g, OopsInGenClosure* blk, uint n_threads);
 
   void inline_write_ref_field_gc(void* field, oop new_val) {
-    jbyte* byte = byte_for(field);
+    CardValue* byte = byte_for(field);
     *byte = youngergen_card;
   }
   void write_ref_field_gc_work(void* field, oop new_val) {
@@ -140,32 +140,32 @@
 
   void invalidate_or_clear(Generation* old_gen);
 
-  bool is_prev_nonclean_card_val(jbyte v) {
+  bool is_prev_nonclean_card_val(CardValue v) {
     return
       youngergen_card <= v &&
       v <= cur_youngergen_and_prev_nonclean_card &&
       v != _cur_youngergen_card_val;
   }
 
-  static bool youngergen_may_have_been_dirty(jbyte cv) {
+  static bool youngergen_may_have_been_dirty(CardValue cv) {
     return cv == CardTableRS::cur_youngergen_and_prev_nonclean_card;
   }
 
   // *** Support for parallel card scanning.
 
   // dirty and precleaned are equivalent wrt younger_refs_iter.
-  static bool card_is_dirty_wrt_gen_iter(jbyte cv) {
+  static bool card_is_dirty_wrt_gen_iter(CardValue cv) {
     return cv == dirty_card || cv == precleaned_card;
   }
 
   // Returns "true" iff the value "cv" will cause the card containing it
   // to be scanned in the current traversal.  May be overridden by
   // subtypes.
-  bool card_will_be_scanned(jbyte cv);
+  bool card_will_be_scanned(CardValue cv);
 
   // Returns "true" iff the value "cv" may have represented a dirty card at
   // some point.
-  bool card_may_have_been_dirty(jbyte cv);
+  bool card_may_have_been_dirty(CardValue cv);
 
   // Iterate over the portion of the card-table which covers the given
   // region mr in the given space and apply cl to any dirty sub-regions
@@ -185,7 +185,7 @@
   // covered region.  Each entry of these arrays is the lowest non-clean
   // card of the corresponding chunk containing part of an object from the
   // previous chunk, or else NULL.
-  typedef jbyte*  CardPtr;
+  typedef CardValue* CardPtr;
   typedef CardPtr* CardArr;
   CardArr* _lowest_non_clean;
   size_t*  _lowest_non_clean_chunk_size;
@@ -199,15 +199,19 @@
   DirtyCardToOopClosure* _dirty_card_closure;
   CardTableRS* _ct;
   bool _is_par;
+
+public:
+
+  typedef CardTable::CardValue CardValue;
 private:
   // Clears the given card, return true if the corresponding card should be
   // processed.
-  inline bool clear_card(jbyte* entry);
+  inline bool clear_card(CardValue* entry);
   // Work methods called by the clear_card()
-  inline bool clear_card_serial(jbyte* entry);
-  inline bool clear_card_parallel(jbyte* entry);
+  inline bool clear_card_serial(CardValue* entry);
+  inline bool clear_card_parallel(CardValue* entry);
   // check alignment of pointer
-  bool is_word_aligned(jbyte* entry);
+  bool is_word_aligned(CardValue* entry);
 
 public:
   ClearNoncleanCardWrapper(DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct, bool is_par);
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -509,9 +509,6 @@
   void print_heap_before_gc();
   void print_heap_after_gc();
 
-  // An object is scavengable if its location may move during a scavenge.
-  // (A scavenge is a GC which is not a full GC.)
-  virtual bool is_scavengable(oop obj) = 0;
   // Registering and unregistering an nmethod (compiled code) with the heap.
   // Override with specific mechanism for each specialized heap type.
   virtual void register_nmethod(nmethod* nm) {}
--- a/src/hotspot/share/gc/shared/gcStats.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/gcStats.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,4 @@
 #include "gc/shared/gcStats.hpp"
 #include "gc/shared/gcUtil.inline.hpp"
 
-GCStats::GCStats() {
-    _avg_promoted       = new AdaptivePaddedNoZeroDevAverage(
-                                                  AdaptiveSizePolicyWeight,
-                                                  PromotedPadding);
-}
+GCStats::GCStats() : _avg_promoted(new AdaptivePaddedNoZeroDevAverage(AdaptiveSizePolicyWeight, PromotedPadding)) {}
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -47,6 +47,7 @@
 #include "gc/shared/genOopClosures.inline.hpp"
 #include "gc/shared/generationSpec.hpp"
 #include "gc/shared/oopStorageParState.inline.hpp"
+#include "gc/shared/scavengableNMethods.hpp"
 #include "gc/shared/space.hpp"
 #include "gc/shared/strongRootsScope.hpp"
 #include "gc/shared/weakProcessor.hpp"
@@ -175,6 +176,15 @@
   return heap_rs->base();
 }
 
+class GenIsScavengable : public BoolObjectClosure {
+public:
+  bool do_object_b(oop obj) {
+    return GenCollectedHeap::heap()->is_in_young(obj);
+  }
+};
+
+static GenIsScavengable _is_scavengable;
+
 void GenCollectedHeap::post_initialize() {
   CollectedHeap::post_initialize();
   ref_processing_init();
@@ -186,6 +196,8 @@
                          def_new_gen->from()->capacity());
 
   MarkSweep::initialize();
+
+  ScavengableNMethods::initialize(&_is_scavengable);
 }
 
 void GenCollectedHeap::ref_processing_init() {
@@ -699,11 +711,23 @@
 }
 
 void GenCollectedHeap::register_nmethod(nmethod* nm) {
-  CodeCache::register_scavenge_root_nmethod(nm);
+  ScavengableNMethods::register_nmethod(nm);
+}
+
+void GenCollectedHeap::unregister_nmethod(nmethod* nm) {
+  ScavengableNMethods::unregister_nmethod(nm);
 }
 
 void GenCollectedHeap::verify_nmethod(nmethod* nm) {
-  CodeCache::verify_scavenge_root_nmethod(nm);
+  ScavengableNMethods::verify_nmethod(nm);
+}
+
+void GenCollectedHeap::flush_nmethod(nmethod* nm) {
+  // Do nothing.
+}
+
+void GenCollectedHeap::prune_scavengable_nmethods() {
+  ScavengableNMethods::prune_nmethods();
 }
 
 HeapWord* GenCollectedHeap::satisfy_failed_allocation(size_t size, bool is_tlab) {
@@ -847,7 +871,7 @@
       assert(code_roots != NULL, "must supply closure for code cache");
 
       // We only visit parts of the CodeCache when scavenging.
-      CodeCache::scavenge_root_nmethods_do(code_roots);
+      ScavengableNMethods::nmethods_do(code_roots);
     }
     if (so & SO_AllCodeCache) {
       assert(code_roots != NULL, "must supply closure for code cache");
@@ -859,7 +883,7 @@
     // Verify that the code cache contents are not subject to
     // movement by a scavenging collection.
     DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, !CodeBlobToOopClosure::FixRelocations));
-    DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable));
+    DEBUG_ONLY(ScavengableNMethods::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable));
   }
 }
 
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -249,13 +249,13 @@
   bool is_in_partial_collection(const void* p);
 #endif
 
-  virtual bool is_scavengable(oop obj) {
-    return is_in_young(obj);
-  }
-
   // Optimized nmethod scanning support routines
   virtual void register_nmethod(nmethod* nm);
-  virtual void verify_nmethod(nmethod* nmethod);
+  virtual void unregister_nmethod(nmethod* nm);
+  virtual void verify_nmethod(nmethod* nm);
+  virtual void flush_nmethod(nmethod* nm);
+
+  void prune_scavengable_nmethods();
 
   // Iteration functions.
   void oop_iterate(OopIterateClosure* cl);
--- a/src/hotspot/share/gc/shared/parallelCleaning.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -70,9 +70,6 @@
 
 CodeCacheUnloadingTask::~CodeCacheUnloadingTask() {
   CodeCache::verify_clean_inline_caches();
-
-  guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be");
-
   CodeCache::verify_icholder_relocations();
 }
 
--- a/src/hotspot/share/gc/shared/ptrQueue.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/ptrQueue.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -36,18 +36,16 @@
 
 #include <new>
 
-PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) :
+PtrQueue::PtrQueue(PtrQueueSet* qset, bool active) :
   _qset(qset),
   _active(active),
-  _permanent(permanent),
   _index(0),
   _capacity_in_bytes(0),
-  _buf(NULL),
-  _lock(NULL)
+  _buf(NULL)
 {}
 
 PtrQueue::~PtrQueue() {
-  assert(_permanent || (_buf == NULL), "queue must be flushed before delete");
+  assert(_buf == NULL, "queue must be flushed before delete");
 }
 
 void PtrQueue::flush_impl() {
@@ -271,23 +269,13 @@
       return;
     }
 
-    if (_lock) {
-      assert(_lock->owned_by_self(), "Required.");
-
-      BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
-      _buf = NULL;         // clear shared _buf field
-
-      qset()->enqueue_completed_buffer(node);
-      assert(_buf == NULL, "multiple enqueuers appear to be racing");
-    } else {
-      BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
-      if (qset()->process_or_enqueue_completed_buffer(node)) {
-        // Recycle the buffer. No allocation.
-        assert(_buf == BufferNode::make_buffer_from_node(node), "invariant");
-        assert(capacity() == qset()->buffer_size(), "invariant");
-        reset();
-        return;
-      }
+    BufferNode* node = BufferNode::make_node_from_buffer(_buf, index());
+    if (qset()->process_or_enqueue_completed_buffer(node)) {
+      // Recycle the buffer. No allocation.
+      assert(_buf == BufferNode::make_buffer_from_node(node), "invariant");
+      assert(capacity() == qset()->buffer_size(), "invariant");
+      reset();
+      return;
     }
   }
   // Set capacity in case this is the first allocation.
--- a/src/hotspot/share/gc/shared/ptrQueue.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/ptrQueue.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -54,11 +54,6 @@
   // Whether updates should be logged.
   bool _active;
 
-  // If true, the queue is permanent, and doesn't need to deallocate
-  // its buffer in the destructor (since that obtains a lock which may not
-  // be legally locked by then.
-  const bool _permanent;
-
   // The (byte) index at which an object was last enqueued.  Starts at
   // capacity_in_bytes (indicating an empty buffer) and goes towards zero.
   // Value is always pointer-size aligned.
@@ -111,27 +106,20 @@
     return byte_index_to_index(capacity_in_bytes());
   }
 
-  // If there is a lock associated with this buffer, this is that lock.
-  Mutex* _lock;
-
   PtrQueueSet* qset() { return _qset; }
-  bool is_permanent() const { return _permanent; }
 
   // Process queue entries and release resources.
   void flush_impl();
 
   // Initialize this queue to contain a null buffer, and be part of the
   // given PtrQueueSet.
-  PtrQueue(PtrQueueSet* qset, bool permanent = false, bool active = false);
+  PtrQueue(PtrQueueSet* qset, bool active = false);
 
-  // Requires queue flushed or permanent.
+  // Requires queue flushed.
   ~PtrQueue();
 
 public:
 
-  // Associate a lock with a ptr queue.
-  void set_lock(Mutex* lock) { _lock = lock; }
-
   // Forcibly set empty.
   void reset() {
     if (_buf != NULL) {
--- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -35,14 +35,14 @@
 #include "runtime/threadSMR.hpp"
 #include "runtime/vmThread.hpp"
 
-SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent) :
+SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset) :
   // SATB queues are only active during marking cycles. We create
   // them with their active field set to false. If a thread is
   // created during a cycle and its SATB queue needs to be activated
   // before the thread starts running, we'll need to set its active
   // field to true. This must be done in the collector-specific
   // BarrierSet thread attachment protocol.
-  PtrQueue(qset, permanent, false /* active */)
+  PtrQueue(qset, false /* active */)
 { }
 
 void SATBMarkQueue::flush() {
--- a/src/hotspot/share/gc/shared/satbMarkQueue.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -55,7 +55,7 @@
   inline void apply_filter(Filter filter_out);
 
 public:
-  SATBMarkQueue(SATBMarkQueueSet* qset, bool permanent = false);
+  SATBMarkQueue(SATBMarkQueueSet* qset);
 
   // Process queue entries and free resources.
   void flush();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/scavengableNMethods.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "code/codeCache.hpp"
+#include "code/nmethod.hpp"
+#include "gc/shared/scavengableNMethods.hpp"
+#include "gc/shared/scavengableNMethodsData.hpp"
+#include "memory/universe.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "utilities/debug.hpp"
+
+static ScavengableNMethodsData gc_data(nmethod* nm) {
+  return ScavengableNMethodsData(nm);
+}
+
+nmethod* ScavengableNMethods::_head = NULL;
+BoolObjectClosure* ScavengableNMethods::_is_scavengable = NULL;
+
+void ScavengableNMethods::initialize(BoolObjectClosure* is_scavengable) {
+  _is_scavengable = is_scavengable;
+}
+
+// Conditionally adds the nmethod to the list if it is
+// not already on the list and has a scavengeable root.
+void ScavengableNMethods::register_nmethod(nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  ScavengableNMethodsData data = gc_data(nm);
+
+  if (data.on_list() || !has_scavengable_oops(nm)) {
+    return;
+  }
+
+  data.set_on_list();
+  data.set_next(_head);
+
+  _head = nm;
+}
+
+void ScavengableNMethods::unregister_nmethod(nmethod* nm) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  if (gc_data(nm).on_list()) {
+    nmethod* prev = NULL;
+    for (nmethod* cur = _head; cur != NULL; cur = gc_data(cur).next()) {
+      if (cur == nm) {
+        unlist_nmethod(cur, prev);
+        return;
+      }
+      prev = cur;
+    }
+  }
+}
+
+#ifndef PRODUCT
+
+class DebugScavengableOops: public OopClosure {
+  BoolObjectClosure* _is_scavengable;
+  nmethod*           _nm;
+  bool               _ok;
+public:
+  DebugScavengableOops(BoolObjectClosure* is_scavengable, nmethod* nm) :
+      _is_scavengable(is_scavengable),
+      _nm(nm),
+      _ok(true) { }
+
+  bool ok() { return _ok; }
+  virtual void do_oop(oop* p) {
+    if (*p == NULL || !_is_scavengable->do_object_b(*p)) {
+      return;
+    }
+
+    if (_ok) {
+      _nm->print_nmethod(true);
+      _ok = false;
+    }
+    tty->print_cr("*** scavengable oop " PTR_FORMAT " found at " PTR_FORMAT " (offset %d)",
+                  p2i(*p), p2i(p), (int)((intptr_t)p - (intptr_t)_nm));
+    (*p)->print();
+  }
+  virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
+};
+
+#endif // PRODUCT
+
+void ScavengableNMethods::verify_nmethod(nmethod* nm) {
+#ifndef PRODUCT
+  if (!gc_data(nm).on_list()) {
+    // Actually look inside, to verify the claim that it's clean.
+    DebugScavengableOops cl(_is_scavengable, nm);
+    nm->oops_do(&cl);
+    if (!cl.ok())
+      fatal("found an unadvertised bad scavengable oop in the code cache");
+  }
+  assert(gc_data(nm).not_marked(), "");
+#endif // PRODUCT
+}
+
+class HasScavengableOops: public OopClosure {
+  BoolObjectClosure* _is_scavengable;
+  bool               _found;
+public:
+  HasScavengableOops(BoolObjectClosure* is_scavengable, nmethod* nm) :
+      _is_scavengable(is_scavengable),
+      _found(false) {}
+
+  bool found() { return _found; }
+  virtual void do_oop(oop* p) {
+    if (!_found && *p != NULL && _is_scavengable->do_object_b(*p)) {
+      _found = true;
+    }
+  }
+  virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
+};
+
+bool ScavengableNMethods::has_scavengable_oops(nmethod* nm) {
+  HasScavengableOops cl(_is_scavengable, nm);
+  nm->oops_do(&cl);
+  return cl.found();
+}
+
+// Walk the list of methods which might contain oops to the java heap.
+void ScavengableNMethods::nmethods_do_and_prune(CodeBlobToOopClosure* cl) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  debug_only(mark_on_list_nmethods());
+
+  nmethod* prev = NULL;
+  nmethod* cur = _head;
+  while (cur != NULL) {
+    assert(cur->is_alive(), "Must be");
+
+    ScavengableNMethodsData data = gc_data(cur);
+    debug_only(data.clear_marked());
+    assert(data.on_list(), "else shouldn't be on this list");
+
+    if (cl != NULL) {
+      cl->do_code_blob(cur);
+    }
+
+    nmethod* const next = data.next();
+
+    if (!has_scavengable_oops(cur)) {
+      unlist_nmethod(cur, prev);
+    } else {
+      prev = cur;
+    }
+
+    cur = next;
+  }
+
+  // Check for stray marks.
+  debug_only(verify_unlisted_nmethods(NULL));
+}
+
+void ScavengableNMethods::prune_nmethods() {
+  nmethods_do_and_prune(NULL /* No closure */);
+}
+
+// Walk the list of methods which might contain oops to the java heap.
+void ScavengableNMethods::nmethods_do(CodeBlobToOopClosure* cl) {
+  nmethods_do_and_prune(cl);
+}
+
+#ifndef PRODUCT
+void ScavengableNMethods::asserted_non_scavengable_nmethods_do(CodeBlobClosure* cl) {
+  // While we are here, verify the integrity of the list.
+  mark_on_list_nmethods();
+  for (nmethod* cur = _head; cur != NULL; cur = gc_data(cur).next()) {
+    assert(gc_data(cur).on_list(), "else shouldn't be on this list");
+    gc_data(cur).clear_marked();
+  }
+  verify_unlisted_nmethods(cl);
+}
+#endif // PRODUCT
+
+void ScavengableNMethods::unlist_nmethod(nmethod* nm, nmethod* prev) {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  assert((prev == NULL && _head == nm) ||
+         (prev != NULL && gc_data(prev).next() == nm), "precondition");
+
+  ScavengableNMethodsData data = gc_data(nm);
+
+  if (prev == NULL) {
+    _head = data.next();
+  } else {
+    gc_data(prev).set_next(data.next());
+  }
+  data.set_next(NULL);
+  data.clear_on_list();
+}
+
+#ifndef PRODUCT
+// Temporarily mark nmethods that are claimed to be on the scavenge list.
+void ScavengableNMethods::mark_on_list_nmethods() {
+  NMethodIterator iter(NMethodIterator::only_alive);
+  while(iter.next()) {
+    nmethod* nm = iter.method();
+    ScavengableNMethodsData data = gc_data(nm);
+    assert(data.not_marked(), "clean state");
+    if (data.on_list())
+      data.set_marked();
+  }
+}
+
+// If the closure is given, run it on the unlisted nmethods.
+// Also make sure that the effects of mark_on_list_nmethods is gone.
+void ScavengableNMethods::verify_unlisted_nmethods(CodeBlobClosure* cl) {
+  NMethodIterator iter(NMethodIterator::only_alive);
+  while(iter.next()) {
+    nmethod* nm = iter.method();
+
+    verify_nmethod(nm);
+
+    if (cl != NULL && !gc_data(nm).on_list()) {
+      cl->do_code_blob(nm);
+    }
+  }
+}
+
+#endif //PRODUCT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/scavengableNMethods.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_SCAVENGABLENMETHODS_HPP
+#define SHARE_GC_SHARED_SCAVENGABLENMETHODS_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/macros.hpp"
+
+class BoolObjectClosure;
+class CodeBlobClosure;
+class CodeBlobToOopClosure;
+class nmethod;
+
+class ScavengableNMethods : public AllStatic {
+  friend class VMStructs;
+
+  static nmethod*           _head;
+  static BoolObjectClosure* _is_scavengable;
+
+public:
+  static void initialize(BoolObjectClosure* is_scavengable);
+
+  static void register_nmethod(nmethod* nm);
+  static void unregister_nmethod(nmethod* nm);
+  static void verify_nmethod(nmethod* nm);
+
+  // Remove nmethods that no longer have scavengable oops.
+  static void prune_nmethods();
+
+  // Apply closure to every scavengable nmethod.
+  // Remove nmethods that no longer have scavengable oops.
+  static void nmethods_do(CodeBlobToOopClosure* cl);
+
+  static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* cl) PRODUCT_RETURN;
+
+private:
+  static void nmethods_do_and_prune(CodeBlobToOopClosure* cl);
+  static void unlist_nmethod(nmethod* nm, nmethod* prev);
+
+  static bool has_scavengable_oops(nmethod* nm);
+
+  static void mark_on_list_nmethods() PRODUCT_RETURN;
+  static void verify_unlisted_nmethods(CodeBlobClosure* cl) PRODUCT_RETURN;
+};
+
+#endif // SHARE_GC_SHARED_SCAVENGABLENMETHODS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/scavengableNMethodsData.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_SCAVENGABLENMETHODDATAS_HPP
+#define SHARE_GC_SHARED_SCAVENGABLENMETHODDATAS_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class nmethod;
+
+class ScavengableNMethodsData : public CHeapObj<mtGC> {
+  // State bits put into the two lower alignment bits.
+  static const uintptr_t state_bits = 2;
+  static const uintptr_t state_mask = (1 << state_bits) - 1;
+  static const uintptr_t state_on_list = 0x1;
+  static const uintptr_t state_marked  = 0x2;
+
+  // nmethod containing the GC data.
+  nmethod* const _nm;
+
+  // The data is stored as a bit pattern in a void* inside the nmethod.
+  uintptr_t data() const                    { return reinterpret_cast<uintptr_t>(_nm->gc_data<void>()); }
+  void set_data(uintptr_t data) const       { _nm->set_gc_data(reinterpret_cast<void*>(data)); }
+
+  jbyte state() const                       { return data() & state_mask; }
+  void set_state(jbyte state) const         { set_data((data() & ~state_mask) | state); }
+
+  uintptr_t from_nmethod(nmethod* nm) const { return reinterpret_cast<uintptr_t>(nm); }
+  nmethod* to_nmethod(uintptr_t data) const { return reinterpret_cast<nmethod*>(data); }
+
+public:
+  ScavengableNMethodsData(nmethod* nm) : _nm(nm) {
+    assert(is_aligned(nm, 4), "Must be aligned to fit state bits");
+  }
+
+  // Scavengable oop support
+  bool  on_list() const { return (state() & state_on_list) != 0; }
+  void  set_on_list()   { set_state(state_on_list); }
+  void  clear_on_list() { set_state(0); }
+
+#ifndef PRODUCT
+  void  set_marked()   { set_state(state() | state_marked); }
+  void  clear_marked() { set_state(state() & ~state_marked); }
+  bool  not_marked()   { return (state() & ~state_on_list) == 0; }
+  // N.B. there is no positive marked query, and we only use the not_marked query for asserts.
+#endif //PRODUCT
+
+  nmethod* next() const     { return to_nmethod(data() & ~state_mask); }
+  void set_next(nmethod *n) { set_data(from_nmethod(n) | state()); }
+};
+
+#endif // SHARE_GC_SHARED_SCAVENGABLENMETHODDATAS_HPP
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -269,21 +269,13 @@
   *list = entry;
 }
 
-bool StringDedupTable::equals(typeArrayOop value1, typeArrayOop value2) {
-  return (oopDesc::equals(value1, value2) ||
-          (value1->length() == value2->length() &&
-          (!memcmp(value1->base(T_BYTE),
-                    value2->base(T_BYTE),
-                    value1->length() * sizeof(jbyte)))));
-}
-
 typeArrayOop StringDedupTable::lookup(typeArrayOop value, bool latin1, unsigned int hash,
                                       StringDedupEntry** list, uintx &count) {
   for (StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) {
     if (entry->hash() == hash && entry->latin1() == latin1) {
       oop* obj_addr = (oop*)entry->obj_addr();
       oop obj = NativeAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(obj_addr);
-      if (equals(value, static_cast<typeArrayOop>(obj))) {
+      if (java_lang_String::value_equals(value, static_cast<typeArrayOop>(obj))) {
         obj = NativeAccess<ON_PHANTOM_OOP_REF>::oop_load(obj_addr);
         return static_cast<typeArrayOop>(obj);
       }
@@ -633,7 +625,7 @@
       while (*entry2 != NULL) {
         typeArrayOop value2 = (*entry2)->obj();
         bool latin1_2 = (*entry2)->latin1();
-        guarantee(latin1_1 != latin1_2 || !equals(value1, value2), "Table entries must not have identical arrays");
+        guarantee(latin1_1 != latin1_2 || !java_lang_String::value_equals(value1, value2), "Table entries must not have identical arrays");
         entry2 = (*entry2)->next_addr();
       }
       entry1 = (*entry1)->next_addr();
--- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -199,8 +199,6 @@
     return _table->_hash_seed == 0;
   }
 
-  static bool equals(typeArrayOop value1, typeArrayOop value2);
-
   // Computes the hash code for the given character array, using the
   // currently active hash function and hash seed.
   static unsigned int hash_code(typeArrayOop value, bool latin1);
--- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -27,6 +27,7 @@
 
 #include "gc/shared/ageTable.hpp"
 #include "gc/shared/cardGeneration.hpp"
+#include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/genCollectedHeap.hpp"
@@ -119,12 +120,12 @@
   nonstatic_field(CardTable,                   _last_valid_index,                             const size_t)                          \
   nonstatic_field(CardTable,                   _page_size,                                    const size_t)                          \
   nonstatic_field(CardTable,                   _byte_map_size,                                const size_t)                          \
-  nonstatic_field(CardTable,                   _byte_map,                                     jbyte*)                                \
+  nonstatic_field(CardTable,                   _byte_map,                                     CardTable::CardValue*)                                \
   nonstatic_field(CardTable,                   _cur_covered_regions,                          int)                                   \
   nonstatic_field(CardTable,                   _covered,                                      MemRegion*)                            \
   nonstatic_field(CardTable,                   _committed,                                    MemRegion*)                            \
   nonstatic_field(CardTable,                   _guard_region,                                 MemRegion)                             \
-  nonstatic_field(CardTable,                   _byte_map_base,                                jbyte*)                                \
+  nonstatic_field(CardTable,                   _byte_map_base,                                CardTable::CardValue*)                                \
   nonstatic_field(CardTableBarrierSet,         _defer_initial_card_mark,                      bool)                                  \
   nonstatic_field(CardTableBarrierSet,         _card_table,                                   CardTable*)                            \
                                                                                                                                      \
@@ -217,6 +218,7 @@
   /* Miscellaneous other GC types */                                      \
                                                                           \
   declare_toplevel_type(AgeTable)                                         \
+  declare_toplevel_type(CardTable::CardValue)                             \
   declare_toplevel_type(Generation::StatRecord)                           \
   declare_toplevel_type(GenerationSpec)                                   \
   declare_toplevel_type(HeapWord)                                         \
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -226,7 +226,10 @@
 
     template <typename T>
     static void oop_store_in_heap(T* addr, oop value) {
-      ShenandoahBarrierSet::barrier_set()->write_ref_field_pre_work(addr, value);
+      const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+      if (keep_alive) {
+        ShenandoahBarrierSet::barrier_set()->write_ref_field_pre_work(addr, value);
+      }
       Raw::oop_store(addr, value);
     }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -58,7 +58,8 @@
     expected = res;
   } while ((! oopDesc::equals_raw(compare_value, expected)) && oopDesc::equals_raw(resolve_forwarded(compare_value), resolve_forwarded(expected)));
   if (oopDesc::equals_raw(expected, compare_value)) {
-    if (ShenandoahSATBBarrier && !CompressedOops::is_null(compare_value)) {
+    const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+    if (keep_alive && ShenandoahSATBBarrier && !CompressedOops::is_null(compare_value)) {
       ShenandoahBarrierSet::barrier_set()->enqueue(compare_value);
     }
   }
@@ -70,7 +71,8 @@
 inline oop ShenandoahBarrierSet::AccessBarrier<decorators, BarrierSetT>::oop_atomic_xchg_in_heap(oop new_value, T* addr) {
   oop previous = Raw::oop_atomic_xchg(new_value, addr);
   if (ShenandoahSATBBarrier) {
-    if (!CompressedOops::is_null(previous)) {
+    const bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0;
+    if (keep_alive && !CompressedOops::is_null(previous)) {
       ShenandoahBarrierSet::barrier_set()->enqueue(previous);
     }
   }
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -48,7 +48,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.inline.hpp"
 
-template<UpdateRefsMode UPDATE_REFS, StringDedupMode STRING_DEDUP>
+template<UpdateRefsMode UPDATE_REFS>
 class ShenandoahInitMarkRootsClosure : public OopClosure {
 private:
   ShenandoahObjToScanQueue* _queue;
@@ -57,7 +57,7 @@
 
   template <class T>
   inline void do_oop_work(T* p) {
-    ShenandoahConcurrentMark::mark_through_ref<T, UPDATE_REFS, STRING_DEDUP>(p, _heap, _queue, _mark_context);
+    ShenandoahConcurrentMark::mark_through_ref<T, UPDATE_REFS, NO_DEDUP>(p, _heap, _queue, _mark_context);
   }
 
 public:
@@ -99,13 +99,8 @@
 
     ShenandoahObjToScanQueue* q = queues->queue(worker_id);
 
-    if (ShenandoahStringDedup::is_enabled()) {
-      ShenandoahInitMarkRootsClosure<UPDATE_REFS, ENQUEUE_DEDUP> mark_cl(q);
-      do_work(heap, &mark_cl, worker_id);
-    } else {
-      ShenandoahInitMarkRootsClosure<UPDATE_REFS, NO_DEDUP> mark_cl(q);
-      do_work(heap, &mark_cl, worker_id);
-    }
+    ShenandoahInitMarkRootsClosure<UPDATE_REFS> mark_cl(q);
+    do_work(heap, &mark_cl, worker_id);
   }
 
 private:
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -559,9 +559,6 @@
   size_t obj_size(oop obj) const;
   virtual ptrdiff_t cell_header_size() const;
 
-  // All objects can potentially move
-  bool is_scavengable(oop obj) { return true; };
-
   void collect(GCCause::Cause cause);
   void do_full_collection(bool clear_all_soft_refs);
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkCompact.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -123,8 +123,6 @@
 
   heap->make_parsable(true);
 
-  CodeCache::gc_prologue();
-
   OrderAccess::fence();
 
   phase1_mark_heap();
@@ -168,7 +166,6 @@
   }
   FREE_C_HEAP_ARRAY(ShenandoahHeapRegionSet*, worker_slices);
 
-  CodeCache::gc_epilogue();
   JvmtiExport::gc_epilogue();
 
   heap->set_full_gc_move_in_progress(false);
--- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -47,7 +47,11 @@
   f(scan_code_roots,                                "    S: Code Cache Roots")          \
   f(scan_universe_roots,                            "    S: Universe Roots")            \
   f(scan_jni_roots,                                 "    S: JNI Roots")                 \
+  f(scan_jvmti_weak_roots,                          "    S: JVMTI Weak Roots")          \
+  f(scan_jfr_weak_roots,                            "    S: JFR Weak Roots")            \
   f(scan_jni_weak_roots,                            "    S: JNI Weak Roots")            \
+  f(scan_stringtable_roots,                         "    S: String Table Roots")        \
+  f(scan_vm_weak_roots,                             "    S: VM Weak Roots")             \
   f(scan_synchronizer_roots,                        "    S: Synchronizer Roots")        \
   f(scan_management_roots,                          "    S: Management Roots")          \
   f(scan_system_dictionary_roots,                   "    S: System Dict Roots")         \
@@ -68,7 +72,11 @@
   f(update_code_roots,                              "    U: Code Cache Roots")          \
   f(update_universe_roots,                          "    U: Universe Roots")            \
   f(update_jni_roots,                               "    U: JNI Roots")                 \
+  f(update_jvmti_weak_roots,                        "    U: JVMTI Weak Roots")          \
+  f(update_jfr_weak_roots,                          "    U: JFR Weak Roots")            \
   f(update_jni_weak_roots,                          "    U: JNI Weak Roots")            \
+  f(update_stringtable_roots,                       "    U: String Table Roots")        \
+  f(update_vm_weak_roots,                           "    U: VM Weak Roots")             \
   f(update_synchronizer_roots,                      "    U: Synchronizer Roots")        \
   f(update_management_roots,                        "    U: Management Roots")          \
   f(update_system_dictionary_roots,                 "    U: System Dict Roots")         \
@@ -97,7 +105,11 @@
   f(evac_code_roots,                                "    E: Code Cache Roots")          \
   f(evac_universe_roots,                            "    E: Universe Roots")            \
   f(evac_jni_roots,                                 "    E: JNI Roots")                 \
+  f(evac_jvmti_weak_roots,                          "    E: JVMTI Weak Roots")          \
+  f(evac_jfr_weak_roots,                            "    E: JFR Weak Roots")            \
   f(evac_jni_weak_roots,                            "    E: JNI Weak Roots")            \
+  f(evac_stringtable_roots,                         "    E: String Table Roots")        \
+  f(evac_vm_weak_roots,                             "    E: VM Weak Roots")             \
   f(evac_synchronizer_roots,                        "    E: Synchronizer Roots")        \
   f(evac_management_roots,                          "    E: Management Roots")          \
   f(evac_system_dictionary_roots,                   "    E: System Dict Roots")         \
@@ -123,7 +135,11 @@
   f(final_update_refs_code_roots,                    "    UR: Code Cache Roots")        \
   f(final_update_refs_universe_roots,                "    UR: Universe Roots")          \
   f(final_update_refs_jni_roots,                     "    UR: JNI Roots")               \
-  f(final_update_refs_jni_weak_roots,                "    UR: JNI Weak Roots")          \
+  f(final_update_jvmti_weak_roots,                   "    UR: JVMTI Weak Roots")        \
+  f(final_update_jfr_weak_roots,                     "    UR: JFR Weak Roots")          \
+  f(final_update_jni_weak_roots,                     "    UR: JNI Weak Roots")          \
+  f(final_update_stringtable_roots,                  "    UR: String Table Roots")      \
+  f(final_update_vm_weak_roots,                      "    UR: VM Weak Roots")           \
   f(final_update_refs_synchronizer_roots,            "    UR: Synchronizer Roots")      \
   f(final_update_refs_management_roots,              "    UR: Management Roots")        \
   f(final_update_refs_system_dict_roots,             "    UR: System Dict Roots")       \
@@ -144,7 +160,11 @@
   f(degen_gc_update_code_roots,                      "    DU: Code Cache Roots")        \
   f(degen_gc_update_universe_roots,                  "    DU: Universe Roots")          \
   f(degen_gc_update_jni_roots,                       "    DU: JNI Roots")               \
+  f(degen_gc_update_jvmti_weak_roots,                "    DU: JVMTI Weak Roots")        \
+  f(degen_gc_update_jfr_weak_roots,                  "    DU: JFR Weak Roots")          \
   f(degen_gc_update_jni_weak_roots,                  "    DU: JNI Weak Roots")          \
+  f(degen_gc_update_stringtable_roots,               "    DU: String Table Roots")      \
+  f(degen_gc_update_vm_weak_roots,                   "    DU: VM Weak Roots")           \
   f(degen_gc_update_synchronizer_roots,              "    DU: Synchronizer Roots")      \
   f(degen_gc_update_management_roots,                "    DU: Management Roots")        \
   f(degen_gc_update_system_dict_roots,               "    DU: System Dict Roots")       \
@@ -166,7 +186,11 @@
   f(init_traversal_gc_code_roots,                    "    TI: Code Cache Roots")        \
   f(init_traversal_gc_universe_roots,                "    TI: Universe Roots")          \
   f(init_traversal_gc_jni_roots,                     "    TI: JNI Roots")               \
+  f(init_traversal_gc_jvmti_weak_roots,              "    TI: JVMTI Weak Roots")        \
+  f(init_traversal_gc_jfr_weak_roots,                "    TI: JFR Weak Roots")          \
   f(init_traversal_gc_jni_weak_roots,                "    TI: JNI Weak Roots")          \
+  f(init_traversal_gc_stringtable_roots,             "    TI: String Table Roots")      \
+  f(init_traversal_gc_vm_weak_roots,                 "    TI: VM Weak Roots")           \
   f(init_traversal_gc_synchronizer_roots,            "    TI: Synchronizer Roots")      \
   f(init_traversal_gc_management_roots,              "    TI: Management Roots")        \
   f(init_traversal_gc_system_dict_roots,             "    TI: System Dict Roots")       \
@@ -185,7 +209,11 @@
   f(final_traversal_gc_code_roots,                   "    TF: Code Cache Roots")        \
   f(final_traversal_gc_universe_roots,               "    TF: Universe Roots")          \
   f(final_traversal_gc_jni_roots,                    "    TF: JNI Roots")               \
+  f(final_traversal_gc_jvmti_weak_roots,             "    TF: JVMTI Weak Roots")        \
+  f(final_traversal_gc_jfr_weak_roots,               "    TF: JFR Weak Roots")          \
   f(final_traversal_gc_jni_weak_roots,               "    TF: JNI Weak Roots")          \
+  f(final_traversal_gc_stringtable_roots,            "    TF: String Table Roots")      \
+  f(final_traversal_gc_vm_weak_roots,                "    TF: VM Weak Roots")           \
   f(final_traversal_gc_synchronizer_roots,           "    TF: Synchronizer Roots")      \
   f(final_traversal_gc_management_roots,             "    TF: Management Roots")        \
   f(final_traversal_gc_system_dict_roots,            "    TF: System Dict Roots")       \
@@ -202,7 +230,11 @@
   f(final_traversal_update_code_roots,               "    TU: Code Cache Roots")        \
   f(final_traversal_update_universe_roots,           "    TU: Universe Roots")          \
   f(final_traversal_update_jni_roots,                "    TU: JNI Roots")               \
+  f(final_traversal_update_jvmti_weak_roots,         "    TU: JVMTI Weak Roots")        \
+  f(final_traversal_update_jfr_weak_roots,           "    TU: JFR Weak Roots")          \
   f(final_traversal_update_jni_weak_roots,           "    TU: JNI Weak Roots")          \
+  f(final_traversal_update_stringtable_roots,        "    TU: String Table Roots")      \
+  f(final_traversal_update_vm_weak_roots,            "    TU: VM Weak Roots")           \
   f(final_traversal_update_synchronizer_roots,       "    TU: Synchronizer Roots")      \
   f(final_traversal_update_management_roots,         "    TU: Management Roots")        \
   f(final_traversal_update_system_dict_roots,        "    TU: System Dict Roots")       \
@@ -225,7 +257,11 @@
   f(full_gc_code_roots,                              "    F: Code Cache Roots")         \
   f(full_gc_universe_roots,                          "    F: Universe Roots")           \
   f(full_gc_jni_roots,                               "    F: JNI Roots")                \
+  f(full_gc_jvmti_weak_roots,                        "    F: JVMTI Weak Roots")         \
+  f(full_gc_jfr_weak_roots,                          "    F: JFR Weak Roots")           \
   f(full_gc_jni_weak_roots,                          "    F: JNI Weak Roots")           \
+  f(full_gc_stringtable_roots,                       "    F: String Table Roots")       \
+  f(full_gc_vm_weak_roots,                           "    F: VM Weak Roots")            \
   f(full_gc_synchronizer_roots,                      "    F: Synchronizer Roots")       \
   f(full_gc_management_roots,                        "    F: Management Roots")         \
   f(full_gc_system_dictionary_roots,                 "    F: System Dict Roots")        \
@@ -279,7 +315,11 @@
   f(CodeCacheRoots,          "CodeCache Roots (ms):")           \
   f(UniverseRoots,           "Universe Roots (ms):")            \
   f(JNIRoots,                "JNI Handles Roots (ms):")         \
+  f(JVMTIWeakRoots,          "JVMTI Weak Roots (ms):")          \
+  f(JFRWeakRoots,            "JFR Weak Roots (ms):")            \
   f(JNIWeakRoots,            "JNI Weak Roots (ms):")            \
+  f(StringTableRoots,        "StringTable Roots(ms):")          \
+  f(VMWeakRoots,             "VM Weak Roots(ms)")               \
   f(ObjectSynchronizerRoots, "ObjectSynchronizer Roots (ms):")  \
   f(ManagementRoots,         "Management Roots (ms):")          \
   f(SystemDictionaryRoots,   "SystemDictionary Roots (ms):")    \
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2015, 2019, Red Hat, Inc. All rights reserved.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
@@ -41,6 +41,25 @@
 #include "runtime/thread.hpp"
 #include "services/management.hpp"
 
+struct PhaseMap {
+  WeakProcessorPhases::Phase            _weak_processor_phase;
+  ShenandoahPhaseTimings::GCParPhases   _shenandoah_phase;
+};
+
+static const struct PhaseMap phase_mapping[] = {
+#if INCLUDE_JVMTI
+  {WeakProcessorPhases::jvmti,       ShenandoahPhaseTimings::JVMTIWeakRoots},
+#endif
+#if INCLUDE_JFR
+  {WeakProcessorPhases::jfr,         ShenandoahPhaseTimings::JFRWeakRoots},
+#endif
+  {WeakProcessorPhases::jni,         ShenandoahPhaseTimings::JNIWeakRoots},
+  {WeakProcessorPhases::stringtable, ShenandoahPhaseTimings::StringTableRoots},
+  {WeakProcessorPhases::vm,          ShenandoahPhaseTimings::VMWeakRoots}
+};
+
+STATIC_ASSERT(sizeof(phase_mapping) / sizeof(PhaseMap) == WeakProcessorPhases::phase_count);
+
 ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers,
                                                  ShenandoahPhaseTimings::Phase phase) :
   _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)),
@@ -48,8 +67,9 @@
   _par_state_string(StringTable::weak_storage()),
   _phase(phase),
   _coderoots_all_iterator(ShenandoahCodeRoots::iterator()),
-  _weak_processor_task(n_workers)
-{
+  _weak_processor_timings(n_workers),
+  _weak_processor_task(&_weak_processor_timings, n_workers),
+  _processed_weak_roots(false) {
   heap->phase_timings()->record_workers_start(_phase);
 
   if (ShenandoahStringDedup::is_enabled()) {
@@ -63,9 +83,32 @@
     StringDedup::gc_epilogue();
   }
 
+  ShenandoahWorkerTimings* worker_times = ShenandoahHeap::heap()->phase_timings()->worker_times();
+
+  if (_processed_weak_roots) {
+    assert(_weak_processor_timings.max_threads() == n_workers(), "Must match");
+    for (uint index = 0; index < WeakProcessorPhases::phase_count; index ++) {
+      weak_processor_timing_to_shenandoah_timing(phase_mapping[index]._weak_processor_phase,
+                                                 phase_mapping[index]._shenandoah_phase,
+                                                 worker_times);
+    }
+  }
+
   ShenandoahHeap::heap()->phase_timings()->record_workers_end(_phase);
 }
 
+void ShenandoahRootProcessor::weak_processor_timing_to_shenandoah_timing(const WeakProcessorPhases::Phase wpp,
+                                                                         const ShenandoahPhaseTimings::GCParPhases spp,
+                                                                         ShenandoahWorkerTimings* worker_times) const {
+  if (WeakProcessorPhases::is_serial(wpp)) {
+    worker_times->record_time_secs(spp, 0, _weak_processor_timings.phase_time_sec(wpp));
+  } else {
+    for (uint index = 0; index < _weak_processor_timings.max_threads(); index ++) {
+      worker_times->record_time_secs(spp, index, _weak_processor_timings.worker_time_sec(index, wpp));
+    }
+  }
+}
+
 void ShenandoahRootProcessor::process_all_roots_slow(OopClosure* oops) {
   CLDToOopClosure clds(oops, ClassLoaderData::_claim_strong);
   CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations);
@@ -193,9 +236,9 @@
     SystemDictionary::oops_do(strong_roots);
   }
   if (jni_weak_roots != NULL) {
-      ShenandoahWorkerTimingsTracker timer(worker_times, ShenandoahPhaseTimings::JNIWeakRoots, worker_id);
-      AlwaysTrueClosure always_true;
-      _weak_processor_task.work<AlwaysTrueClosure, OopClosure>(worker_id, &always_true, jni_weak_roots);
+    AlwaysTrueClosure always_true;
+    _weak_processor_task.work<AlwaysTrueClosure, OopClosure>(worker_id, &always_true, jni_weak_roots);
+    _processed_weak_roots = true;
   }
 
   if (ShenandoahStringDedup::is_enabled() && weak_roots != NULL) {
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -31,6 +31,7 @@
 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
 #include "gc/shared/strongRootsScope.hpp"
 #include "gc/shared/weakProcessor.hpp"
+#include "gc/shared/weakProcessorPhaseTimes.hpp"
 #include "gc/shared/workgroup.hpp"
 #include "memory/allocation.hpp"
 #include "memory/iterator.hpp"
@@ -60,7 +61,9 @@
   ParallelCLDRootIterator   _cld_iterator;
   ShenandoahAllCodeRootsIterator _coderoots_all_iterator;
   CodeBlobClosure* _threads_nmethods_cl;
-  WeakProcessor::Task _weak_processor_task;
+  WeakProcessorPhaseTimes _weak_processor_timings;
+  WeakProcessor::Task     _weak_processor_task;
+  bool                    _processed_weak_roots;
 
   void process_java_roots(OopClosure* scan_non_heap_roots,
                           CLDClosure* scan_strong_clds,
@@ -74,6 +77,10 @@
                         OopClosure* weak_jni_roots,
                         uint worker_i);
 
+  void weak_processor_timing_to_shenandoah_timing(const WeakProcessorPhases::Phase wpp,
+                                                  const ShenandoahPhaseTimings::GCParPhases spp,
+                                                  ShenandoahWorkerTimings* worker_times) const;
+
 public:
   ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers,
                           ShenandoahPhaseTimings::Phase phase);
--- a/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahSATBMarkQueueSet.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -31,7 +31,7 @@
 
 class ShenandoahSATBMarkQueue: public SATBMarkQueue {
 public:
-  ShenandoahSATBMarkQueue(SATBMarkQueueSet* qset) : SATBMarkQueue(qset, /* permanent = */ false) {}
+  ShenandoahSATBMarkQueue(SATBMarkQueueSet* qset) : SATBMarkQueue(qset) {}
   virtual bool should_enqueue_buffer();
 };
 
--- a/src/hotspot/share/gc/z/vmStructs_z.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/vmStructs_z.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,9 @@
 #ifndef SHARE_GC_Z_VMSTRUCTS_Z_HPP
 #define SHARE_GC_Z_VMSTRUCTS_Z_HPP
 
+#include "gc/z/zAttachedArray.hpp"
 #include "gc/z/zCollectedHeap.hpp"
+#include "gc/z/zForwarding.hpp"
 #include "gc/z/zGranuleMap.hpp"
 #include "gc/z/zHeap.hpp"
 #include "gc/z/zPageAllocator.hpp"
@@ -52,7 +54,8 @@
   const int* _ZObjectAlignmentSmall;
 };
 
-typedef ZGranuleMap<ZPageTableEntry> ZGranuleMapForPageTable;
+typedef ZGranuleMap<ZPage*> ZGranuleMapForPageTable;
+typedef ZAttachedArray<ZForwarding, ZForwardingEntry> ZAttachedArrayForForwarding;
 
 #define VM_STRUCTS_ZGC(nonstatic_field, volatile_nonstatic_field, static_field)                      \
   static_field(ZGlobalsForVMStructs,            _instance_p,          ZGlobalsForVMStructs*)         \
@@ -67,27 +70,24 @@
   nonstatic_field(ZCollectedHeap,               _heap,                ZHeap)                         \
                                                                                                      \
   nonstatic_field(ZHeap,                        _page_allocator,      ZPageAllocator)                \
-  nonstatic_field(ZHeap,                        _pagetable,           ZPageTable)                    \
+  nonstatic_field(ZHeap,                        _page_table,          ZPageTable)                    \
                                                                                                      \
   nonstatic_field(ZPage,                        _type,                const uint8_t)                 \
   nonstatic_field(ZPage,                        _seqnum,              uint32_t)                      \
   nonstatic_field(ZPage,                        _virtual,             const ZVirtualMemory)          \
   volatile_nonstatic_field(ZPage,               _top,                 uintptr_t)                     \
-  volatile_nonstatic_field(ZPage,               _refcount,            uint32_t)                      \
-  nonstatic_field(ZPage,                        _forwarding,          ZForwardingTable)              \
                                                                                                      \
   nonstatic_field(ZPageAllocator,               _physical,            ZPhysicalMemoryManager)        \
   nonstatic_field(ZPageAllocator,               _used,                size_t)                        \
                                                                                                      \
   nonstatic_field(ZPageTable,                   _map,                 ZGranuleMapForPageTable)       \
                                                                                                      \
-  nonstatic_field(ZGranuleMapForPageTable,      _map,                 ZPageTableEntry* const)        \
+  nonstatic_field(ZGranuleMapForPageTable,      _map,                 ZPage** const)                 \
                                                                                                      \
   nonstatic_field(ZVirtualMemory,               _start,               uintptr_t)                     \
   nonstatic_field(ZVirtualMemory,               _end,                 uintptr_t)                     \
                                                                                                      \
-  nonstatic_field(ZForwardingTable,             _table,               ZForwardingTableEntry*)        \
-  nonstatic_field(ZForwardingTable,             _size,                size_t)                        \
+  nonstatic_field(ZForwarding,                  _entries,             const ZAttachedArrayForForwarding) \
                                                                                                      \
   nonstatic_field(ZPhysicalMemoryManager,       _max_capacity,        const size_t)                  \
   nonstatic_field(ZPhysicalMemoryManager,       _capacity,            size_t)
@@ -117,11 +117,12 @@
   declare_toplevel_type(ZPage)                                                                       \
   declare_toplevel_type(ZPageAllocator)                                                              \
   declare_toplevel_type(ZPageTable)                                                                  \
-  declare_toplevel_type(ZPageTableEntry)                                                             \
+  declare_toplevel_type(ZAttachedArrayForForwarding)                                                 \
   declare_toplevel_type(ZGranuleMapForPageTable)                                                     \
   declare_toplevel_type(ZVirtualMemory)                                                              \
   declare_toplevel_type(ZForwardingTable)                                                            \
-  declare_toplevel_type(ZForwardingTableEntry)                                                       \
+  declare_toplevel_type(ZForwarding)                                                                 \
+  declare_toplevel_type(ZForwardingEntry)                                                            \
   declare_toplevel_type(ZPhysicalMemoryManager)
 
 #endif // SHARE_GC_Z_VMSTRUCTS_Z_HPP
--- a/src/hotspot/share/gc/z/zArray.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zArray.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -51,6 +51,7 @@
   T at(size_t index) const;
 
   void add(T value);
+  void transfer(ZArray<T>* from);
   void clear();
 };
 
--- a/src/hotspot/share/gc/z/zArray.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zArray.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -80,6 +80,17 @@
 }
 
 template <typename T>
+inline void ZArray<T>::transfer(ZArray<T>* from) {
+  assert(_array == NULL, "Should be empty");
+  _array = from->_array;
+  _size = from->_size;
+  _capacity = from->_capacity;
+  from->_array = NULL;
+  from->_size = 0;
+  from->_capacity = 0;
+}
+
+template <typename T>
 inline void ZArray<T>::clear() {
   _size = 0;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zAttachedArray.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZATTACHEDARRAY_HPP
+#define SHARE_GC_Z_ZATTACHEDARRAY_HPP
+
+#include "utilities/globalDefinitions.hpp"
+
+template <typename ObjectT, typename ArrayT>
+class ZAttachedArray {
+private:
+  const uint32_t _length;
+
+  static size_t object_size();
+
+public:
+  static void* alloc(size_t length);
+  static void free(ObjectT* obj);
+
+  ZAttachedArray(size_t length);
+
+  uint32_t length() const;
+  ArrayT* operator()(const ObjectT* obj) const;
+};
+
+#endif // SHARE_GC_Z_ZATTACHEDARRAY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zAttachedArray.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZATTACHEDARRAY_INLINE_HPP
+#define SHARE_GC_Z_ZATTACHEDARRAY_INLINE_HPP
+
+#include "gc/z/zAttachedArray.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/align.hpp"
+
+template <typename ObjectT, typename ArrayT>
+inline size_t ZAttachedArray<ObjectT, ArrayT>::object_size() {
+  return align_up(sizeof(ObjectT), sizeof(ArrayT));
+}
+
+template <typename ObjectT, typename ArrayT>
+inline void* ZAttachedArray<ObjectT, ArrayT>::alloc(size_t length) {
+  const size_t array_size = sizeof(ArrayT) * length;
+  char* const addr = AllocateHeap(object_size() + array_size, mtGC);
+  ::new (addr + object_size()) ArrayT[length];
+  return addr;
+}
+
+template <typename ObjectT, typename ArrayT>
+inline void ZAttachedArray<ObjectT, ArrayT>::free(ObjectT* obj) {
+  FreeHeap(obj);
+}
+
+template <typename ObjectT, typename ArrayT>
+inline ZAttachedArray<ObjectT, ArrayT>::ZAttachedArray(size_t length) :
+    _length(length) {}
+
+template <typename ObjectT, typename ArrayT>
+inline uint32_t ZAttachedArray<ObjectT, ArrayT>::length() const {
+  return _length;
+}
+
+template <typename ObjectT, typename ArrayT>
+inline ArrayT* ZAttachedArray<ObjectT, ArrayT>::operator()(const ObjectT* obj) const {
+  return reinterpret_cast<ArrayT*>(reinterpret_cast<uintptr_t>(obj) + object_size());
+}
+
+#endif // SHARE_GC_Z_ZATTACHEDARRAY_INLINE_HPP
--- a/src/hotspot/share/gc/z/zBarrier.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zBarrier.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,27 +98,13 @@
 uintptr_t ZBarrier::remap(uintptr_t addr) {
   assert(!ZAddress::is_good(addr), "Should not be good");
   assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
-
-  if (ZHeap::heap()->is_relocating(addr)) {
-    // Forward
-    return ZHeap::heap()->forward_object(addr);
-  }
-
-  // Remap
-  return ZAddress::good(addr);
+  return ZHeap::heap()->remap_object(addr);
 }
 
 uintptr_t ZBarrier::relocate(uintptr_t addr) {
   assert(!ZAddress::is_good(addr), "Should not be good");
   assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
-
-  if (ZHeap::heap()->is_relocating(addr)) {
-    // Relocate
-    return ZHeap::heap()->relocate_object(addr);
-  }
-
-  // Remap
-  return ZAddress::good(addr);
+  return ZHeap::heap()->relocate_object(addr);
 }
 
 uintptr_t ZBarrier::relocate_or_mark(uintptr_t addr) {
--- a/src/hotspot/share/gc/z/zCollectedHeap.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -106,10 +106,6 @@
   return false;
 }
 
-bool ZCollectedHeap::is_scavengable(oop obj) {
-  return false;
-}
-
 bool ZCollectedHeap::is_in(const void* p) const {
   return is_in_reserved(p) && _heap.is_in((uintptr_t)p);
 }
--- a/src/hotspot/share/gc/z/zCollectedHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -71,7 +71,6 @@
   virtual size_t used() const;
 
   virtual bool is_maximal_no_gc() const;
-  virtual bool is_scavengable(oop obj);
   virtual bool is_in(const void* p) const;
   virtual bool is_in_closed_subset(const void* p) const;
 
--- a/src/hotspot/share/gc/z/zDebug.gdb	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zDebug.gdb	Tue Mar 26 09:05:10 2019 -0400
@@ -53,17 +53,17 @@
     printf "Mark:  0x%016llx\tKlass: %s\n", (uintptr_t)$obj->_mark, (char*)$obj->_metadata->_klass->_name->_body
 end
 
-# Print heap page by pagetable index
+# Print heap page by page table index
 define zpp
-    set $page = (ZPage*)((uintptr_t)ZHeap::_heap._pagetable._map._map[($arg0)] & ~1)
+    set $page = (ZPage*)((uintptr_t)ZHeap::_heap._page_table._map._map[($arg0)] & ~1)
     printf "Page %p\n", $page
     print *$page
 end
 
-# Print pagetable
+# Print page_table
 define zpt
     printf "Pagetable (first 128 slots)\n"
-    x/128gx ZHeap::_heap._pagetable._map._map
+    x/128gx ZHeap::_heap._page_table._map._map
 end
 
 # Print live map
@@ -100,7 +100,7 @@
     set $addr          = $arg0
     set $obj           = ((uintptr_t)$addr & ZAddressOffsetMask)
     set $page_index    = $obj >> ZGranuleSizeShift
-    set $page_entry    = (uintptr_t)ZHeap::_heap._pagetable._map._map[$page_index]
+    set $page_entry    = (uintptr_t)ZHeap::_heap._page_table._map._map[$page_index]
     set $page          = (ZPage*)($page_entry & ~1)
     set $page_start    = (uintptr_t)$page._virtual._start
     set $page_end      = (uintptr_t)$page._virtual._end
--- a/src/hotspot/share/gc/z/zDriver.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zDriver.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -43,9 +43,7 @@
 static const ZStatPhasePause      ZPhasePauseMarkEnd("Pause Mark End");
 static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References");
 static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set");
-static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages");
 static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set");
-static const ZStatPhaseConcurrent ZPhaseConcurrentPrepareRelocationSet("Concurrent Prepare Relocation Set");
 static const ZStatPhasePause      ZPhasePauseRelocateStart("Pause Relocate Start");
 static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate");
 static const ZStatCriticalPhase   ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */);
@@ -300,11 +298,6 @@
   ZHeap::heap()->reset_relocation_set();
 }
 
-void ZDriver::concurrent_destroy_detached_pages() {
-  ZStatTimer timer(ZPhaseConcurrentDestroyDetachedPages);
-  ZHeap::heap()->destroy_detached_pages();
-}
-
 void ZDriver::pause_verify() {
   if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) {
     VM_Verify op;
@@ -317,11 +310,6 @@
   ZHeap::heap()->select_relocation_set();
 }
 
-void ZDriver::concurrent_prepare_relocation_set() {
-  ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet);
-  ZHeap::heap()->prepare_relocation_set();
-}
-
 void ZDriver::pause_relocate_start() {
   pause<VM_ZRelocateStart>();
 }
@@ -384,22 +372,16 @@
   // Phase 5: Concurrent Reset Relocation Set
   concurrent_reset_relocation_set();
 
-  // Phase 6: Concurrent Destroy Detached Pages
-  concurrent_destroy_detached_pages();
-
-  // Phase 7: Pause Verify
+  // Phase 6: Pause Verify
   pause_verify();
 
-  // Phase 8: Concurrent Select Relocation Set
+  // Phase 7: Concurrent Select Relocation Set
   concurrent_select_relocation_set();
 
-  // Phase 9: Concurrent Prepare Relocation Set
-  concurrent_prepare_relocation_set();
-
-  // Phase 10: Pause Relocate Start
+  // Phase 8: Pause Relocate Start
   pause_relocate_start();
 
-  // Phase 11: Concurrent Relocate
+  // Phase 9: Concurrent Relocate
   concurrent_relocate();
 }
 
--- a/src/hotspot/share/gc/z/zDriver.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zDriver.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -43,10 +43,8 @@
   void concurrent_mark_continue();
   void concurrent_process_non_strong_references();
   void concurrent_reset_relocation_set();
-  void concurrent_destroy_detached_pages();
   void pause_verify();
   void concurrent_select_relocation_set();
-  void concurrent_prepare_relocation_set();
   void pause_relocate_start();
   void concurrent_relocate();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zForwarding.inline.hpp"
+#include "gc/z/zPage.inline.hpp"
+#include "gc/z/zUtils.inline.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+
+ZForwarding* ZForwarding::create(ZPage* page) {
+  // Allocate table for linear probing. The size of the table must be
+  // a power of two to allow for quick and inexpensive indexing/masking.
+  // The table is sized to have a load factor of 50%, i.e. sized to have
+  // double the number of entries actually inserted.
+  assert(page->live_objects() > 0, "Invalid value");
+  const uint32_t nentries = ZUtils::round_up_power_of_2(page->live_objects() * 2);
+  return ::new (AttachedArray::alloc(nentries)) ZForwarding(page, nentries);
+}
+
+void ZForwarding::destroy(ZForwarding* forwarding) {
+  AttachedArray::free(forwarding);
+}
+
+ZForwarding::ZForwarding(ZPage* page, uint32_t nentries) :
+    _virtual(page->virtual_memory()),
+    _object_alignment_shift(page->object_alignment_shift()),
+    _entries(nentries),
+    _page(page),
+    _refcount(1),
+    _pinned(false) {}
+
+void ZForwarding::verify() const {
+  guarantee(_refcount > 0, "Invalid refcount");
+  guarantee(_page != NULL, "Invalid page");
+
+  uint32_t live_objects = 0;
+
+  for (ZForwardingCursor i = 0; i < _entries.length(); i++) {
+    const ZForwardingEntry entry = at(&i);
+    if (entry.is_empty()) {
+      // Skip empty entries
+      continue;
+    }
+
+    // Check from index
+    guarantee(entry.from_index() < _page->object_max_count(), "Invalid from index");
+
+    // Check for duplicates
+    for (ZForwardingCursor j = i + 1; j < _entries.length(); j++) {
+      const ZForwardingEntry other = at(&j);
+      guarantee(entry.from_index() != other.from_index(), "Duplicate from");
+      guarantee(entry.to_offset() != other.to_offset(), "Duplicate to");
+    }
+
+    live_objects++;
+  }
+
+  // Check number of non-empty entries
+  guarantee(live_objects == _page->live_objects(), "Invalid number of entries");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_ZFORWARDING_HPP
+#define SHARE_GC_Z_ZFORWARDING_HPP
+
+#include "gc/z/zAttachedArray.hpp"
+#include "gc/z/zForwardingEntry.hpp"
+#include "gc/z/zVirtualMemory.hpp"
+
+class ZPage;
+
+typedef uint32_t ZForwardingCursor;
+
+class ZForwarding {
+  friend class VMStructs;
+  friend class ZForwardingTest;
+
+private:
+  typedef ZAttachedArray<ZForwarding, ZForwardingEntry> AttachedArray;
+
+  const ZVirtualMemory _virtual;
+  const size_t         _object_alignment_shift;
+  const AttachedArray  _entries;
+  ZPage*               _page;
+  volatile uint32_t    _refcount;
+  volatile bool        _pinned;
+
+  bool inc_refcount();
+  bool dec_refcount();
+
+  ZForwardingEntry* entries() const;
+  ZForwardingEntry at(ZForwardingCursor* cursor) const;
+  ZForwardingEntry first(uintptr_t from_index, ZForwardingCursor* cursor) const;
+  ZForwardingEntry next(ZForwardingCursor* cursor) const;
+
+  ZForwarding(ZPage* page, uint32_t nentries);
+
+public:
+  static ZForwarding* create(ZPage* page);
+  static void destroy(ZForwarding* forwarding);
+
+  uintptr_t start() const;
+  size_t size() const;
+  size_t object_alignment_shift() const;
+  ZPage* page() const;
+
+  bool is_pinned() const;
+  void set_pinned();
+
+  bool retain_page();
+  void release_page();
+
+  ZForwardingEntry find(uintptr_t from_index) const;
+  ZForwardingEntry find(uintptr_t from_index, ZForwardingCursor* cursor) const;
+  uintptr_t insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingCursor* cursor);
+
+  void verify() const;
+};
+
+#endif // SHARE_GC_Z_ZFORWARDING_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_ZFORWARDING_INLINE_HPP
+#define SHARE_GC_Z_ZFORWARDING_INLINE_HPP
+
+#include "gc/z/zAttachedArray.inline.hpp"
+#include "gc/z/zForwarding.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zHash.inline.hpp"
+#include "gc/z/zHeap.hpp"
+#include "gc/z/zVirtualMemory.inline.hpp"
+#include "runtime/atomic.hpp"
+#include "utilities/debug.hpp"
+
+inline uintptr_t ZForwarding::start() const {
+  return _virtual.start();
+}
+
+inline size_t ZForwarding::size() const {
+  return _virtual.size();
+}
+
+inline size_t ZForwarding::object_alignment_shift() const {
+  return _object_alignment_shift;
+}
+
+inline ZPage* ZForwarding::page() const {
+  return _page;
+}
+
+inline bool ZForwarding::is_pinned() const {
+  return Atomic::load(&_pinned);
+}
+
+inline void ZForwarding::set_pinned() {
+  Atomic::store(true, &_pinned);
+}
+
+inline bool ZForwarding::inc_refcount() {
+  uint32_t refcount = Atomic::load(&_refcount);
+
+  while (refcount > 0) {
+    const uint32_t old_refcount = refcount;
+    const uint32_t new_refcount = old_refcount + 1;
+    const uint32_t prev_refcount = Atomic::cmpxchg(new_refcount, &_refcount, old_refcount);
+    if (prev_refcount == old_refcount) {
+      return true;
+    }
+
+    refcount = prev_refcount;
+  }
+
+  return false;
+}
+
+inline bool ZForwarding::dec_refcount() {
+  assert(_refcount > 0, "Invalid state");
+  return Atomic::sub(1u, &_refcount) == 0u;
+}
+
+inline bool ZForwarding::retain_page() {
+  return inc_refcount();
+}
+
+inline void ZForwarding::release_page() {
+  if (dec_refcount()) {
+    ZHeap::heap()->free_page(_page, true /* reclaimed */);
+    _page = NULL;
+  }
+}
+
+inline ZForwardingEntry* ZForwarding::entries() const {
+  return _entries(this);
+}
+
+inline ZForwardingEntry ZForwarding::at(ZForwardingCursor* cursor) const {
+  return Atomic::load(entries() + *cursor);
+}
+
+inline ZForwardingEntry ZForwarding::first(uintptr_t from_index, ZForwardingCursor* cursor) const {
+  const uint32_t mask = _entries.length() - 1;
+  const uint32_t hash = ZHash::uint32_to_uint32((uint32_t)from_index);
+  *cursor = hash & mask;
+  return at(cursor);
+}
+
+inline ZForwardingEntry ZForwarding::next(ZForwardingCursor* cursor) const {
+  const uint32_t mask = _entries.length() - 1;
+  *cursor = (*cursor + 1) & mask;
+  return at(cursor);
+}
+
+inline ZForwardingEntry ZForwarding::find(uintptr_t from_index) const {
+  ZForwardingCursor dummy;
+  return find(from_index, &dummy);
+}
+
+inline ZForwardingEntry ZForwarding::find(uintptr_t from_index, ZForwardingCursor* cursor) const {
+  // Reading entries in the table races with the atomic CAS done for
+  // insertion into the table. This is safe because each entry is at
+  // most updated once (from -1 to something else).
+  ZForwardingEntry entry = first(from_index, cursor);
+  while (!entry.is_empty()) {
+    if (entry.from_index() == from_index) {
+      // Match found, return matching entry
+      return entry;
+    }
+
+    entry = next(cursor);
+  }
+
+  // Match not found, return empty entry
+  return entry;
+}
+
+inline uintptr_t ZForwarding::insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingCursor* cursor) {
+  const ZForwardingEntry new_entry(from_index, to_offset);
+  const ZForwardingEntry old_entry; // Empty
+
+  for (;;) {
+    const ZForwardingEntry prev_entry = Atomic::cmpxchg(new_entry, entries() + *cursor, old_entry);
+    if (prev_entry.is_empty()) {
+      // Success
+      return to_offset;
+    }
+
+    // Find next empty or matching entry
+    ZForwardingEntry entry = at(cursor);
+    while (!entry.is_empty()) {
+      if (entry.from_index() == from_index) {
+        // Match found, return already inserted address
+        return entry.to_offset();
+      }
+
+      entry = next(cursor);
+    }
+  }
+}
+
+#endif // SHARE_GC_Z_ZFORWARDING_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwardingEntry.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZFORWARDINGENTRY_HPP
+#define SHARE_GC_Z_ZFORWARDINGENTRY_HPP
+
+#include "gc/z/zBitField.hpp"
+#include "memory/allocation.hpp"
+#include "metaprogramming/primitiveConversions.hpp"
+
+//
+// Forwarding entry layout
+// -----------------------
+//
+//   6                      4 4                                             0
+//   3                      2 1                                             0
+//  +------------------------+-----------------------------------------------+
+//  |11111111 11111111 111111|11 11111111 11111111 11111111 11111111 11111111|
+//  +------------------------+-----------------------------------------------+
+//  |                        |
+//  |                        * 41-0 To Object Offset (42-bits)
+//  |
+//  * 63-42 From Object Index (22-bits)
+//
+
+class ZForwardingEntry {
+  friend struct PrimitiveConversions;
+
+private:
+  typedef ZBitField<uint64_t, size_t, 0,  42> field_to_offset;
+  typedef ZBitField<uint64_t, size_t, 42, 22> field_from_index;
+
+  uint64_t _entry;
+
+  static uintptr_t empty() {
+    return (uintptr_t)-1;
+  }
+
+public:
+  ZForwardingEntry() :
+      _entry(empty()) {}
+
+  ZForwardingEntry(size_t from_index, size_t to_offset) :
+      _entry(field_from_index::encode(from_index) |
+             field_to_offset::encode(to_offset)) {}
+
+  bool is_empty() const {
+    return _entry == empty();
+  }
+
+  size_t to_offset() const {
+    return field_to_offset::decode(_entry);
+  }
+
+  size_t from_index() const {
+    return field_from_index::decode(_entry);
+  }
+};
+
+// Needed to allow atomic operations on ZForwardingEntry
+template <>
+struct PrimitiveConversions::Translate<ZForwardingEntry> : public TrueType {
+  typedef ZForwardingEntry Value;
+  typedef uint64_t         Decayed;
+
+  static Decayed decay(Value v) {
+    return v._entry;
+  }
+
+  static Value recover(Decayed d) {
+    ZForwardingEntry entry;
+    entry._entry = d;
+    return entry;
+  }
+};
+
+#endif // SHARE_GC_Z_ZFORWARDINGENTRY_HPP
--- a/src/hotspot/share/gc/z/zForwardingTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zForwardingTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,63 +22,27 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
 #include "gc/z/zForwardingTable.inline.hpp"
-#include "gc/z/zUtils.inline.hpp"
-#include "memory/allocation.inline.hpp"
+#include "gc/z/zGranuleMap.inline.hpp"
 #include "utilities/debug.hpp"
 
-void ZForwardingTable::setup(size_t live_objects) {
-  assert(is_null(), "Should be empty");
-  assert(live_objects > 0, "Invalid size");
+ZForwardingTable::ZForwardingTable() :
+    _map() {}
 
-  // Allocate table for linear probing. The size of the table must be
-  // a power of two to allow for quick and inexpensive indexing/masking.
-  // The table is sized to have a load factor of 50%, i.e. sized to have
-  // double the number of entries actually inserted.
-  _size = ZUtils::round_up_power_of_2(live_objects * 2);
-  _table = MallocArrayAllocator<ZForwardingTableEntry>::allocate(_size, mtGC);
+void ZForwardingTable::insert(ZForwarding* forwarding) {
+  const uintptr_t addr = ZAddress::good(forwarding->start());
+  const size_t size = forwarding->size();
 
-  // Construct table entries
-  for (size_t i = 0; i < _size; i++) {
-    ::new (_table + i) ZForwardingTableEntry();
-  }
+  assert(get(addr) == NULL, "Invalid entry");
+  _map.put(addr, size, forwarding);
 }
 
-void ZForwardingTable::reset() {
-  // Destruct table entries
-  for (size_t i = 0; i < _size; i++) {
-    (_table + i)->~ZForwardingTableEntry();
-  }
-
-  // Free table
-  MallocArrayAllocator<ZForwardingTableEntry>::free(_table);
-  _table = NULL;
-  _size = 0;
-}
-
-void ZForwardingTable::verify(size_t object_max_count, size_t live_objects) const {
-  size_t count = 0;
+void ZForwardingTable::remove(ZForwarding* forwarding) {
+  const uintptr_t addr = ZAddress::good(forwarding->start());
+  const size_t size = forwarding->size();
 
-  for (size_t i = 0; i < _size; i++) {
-    const ZForwardingTableEntry entry = _table[i];
-    if (entry.is_empty()) {
-      // Skip empty entries
-      continue;
-    }
-
-    // Check from index
-    guarantee(entry.from_index() < object_max_count, "Invalid from index");
-
-    // Check for duplicates
-    for (size_t j = i + 1; j < _size; j++) {
-      const ZForwardingTableEntry other = _table[j];
-      guarantee(entry.from_index() != other.from_index(), "Duplicate from");
-      guarantee(entry.to_offset() != other.to_offset(), "Duplicate to");
-    }
-
-    count++;
-  }
-
-  // Check number of non-null entries
-  guarantee(live_objects == count, "Count mismatch");
+  assert(get(addr) == forwarding, "Invalid entry");
+  _map.put(addr, size, NULL);
 }
--- a/src/hotspot/share/gc/z/zForwardingTable.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zForwardingTable.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,36 +24,21 @@
 #ifndef SHARE_GC_Z_ZFORWARDINGTABLE_HPP
 #define SHARE_GC_Z_ZFORWARDINGTABLE_HPP
 
-#include "gc/z/zForwardingTableEntry.hpp"
-#include "memory/allocation.hpp"
+#include "gc/z/zGranuleMap.hpp"
 
-typedef size_t ZForwardingTableCursor;
+class ZForwarding;
 
 class ZForwardingTable {
-  friend class VMStructs;
-  friend class ZForwardingTableTest;
-
 private:
-  ZForwardingTableEntry* _table;
-  size_t                 _size;
-
-  ZForwardingTableEntry at(ZForwardingTableCursor* cursor) const;
-  ZForwardingTableEntry first(uintptr_t from_index, ZForwardingTableCursor* cursor) const;
-  ZForwardingTableEntry next(ZForwardingTableCursor* cursor) const;
+  ZGranuleMap<ZForwarding*> _map;
 
 public:
   ZForwardingTable();
-  ~ZForwardingTable();
 
-  bool is_null() const;
-  void setup(size_t live_objects);
-  void reset();
+  ZForwarding* get(uintptr_t addr) const;
 
-  ZForwardingTableEntry find(uintptr_t from_index) const;
-  ZForwardingTableEntry find(uintptr_t from_index, ZForwardingTableCursor* cursor) const;
-  uintptr_t insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingTableCursor* cursor);
-
-  void verify(size_t object_max_count, size_t live_objects) const;
+  void insert(ZForwarding* forwarding);
+  void remove(ZForwarding* forwarding);
 };
 
 #endif // SHARE_GC_Z_ZFORWARDINGTABLE_HPP
--- a/src/hotspot/share/gc/z/zForwardingTable.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zForwardingTable.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,85 +25,10 @@
 #define SHARE_GC_Z_ZFORWARDINGTABLE_INLINE_HPP
 
 #include "gc/z/zForwardingTable.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zHash.inline.hpp"
-#include "runtime/atomic.hpp"
-#include "utilities/debug.hpp"
-
-inline ZForwardingTable::ZForwardingTable() :
-    _table(NULL),
-    _size(0) {}
-
-inline ZForwardingTable::~ZForwardingTable() {
-  assert(is_null(), "Should be empty");
-}
-
-inline ZForwardingTableEntry ZForwardingTable::at(ZForwardingTableCursor* cursor) const {
-  return _table[*cursor];
-}
-
-inline ZForwardingTableEntry ZForwardingTable::first(uintptr_t from_index, ZForwardingTableCursor* cursor) const {
-  const size_t mask = _size - 1;
-  const size_t hash = ZHash::uint32_to_uint32((uint32_t)from_index);
-  *cursor = hash & mask;
-  return at(cursor);
-}
-
-inline ZForwardingTableEntry ZForwardingTable::next(ZForwardingTableCursor* cursor) const {
-  const size_t mask = _size - 1;
-  *cursor = (*cursor + 1) & mask;
-  return at(cursor);
-}
-
-inline bool ZForwardingTable::is_null() const {
-  return _table == NULL;
-}
-
-inline ZForwardingTableEntry ZForwardingTable::find(uintptr_t from_index) const {
-  ZForwardingTableCursor dummy;
-  return find(from_index, &dummy);
-}
+#include "gc/z/zGranuleMap.inline.hpp"
 
-inline ZForwardingTableEntry ZForwardingTable::find(uintptr_t from_index, ZForwardingTableCursor* cursor) const {
-  // Reading entries in the table races with the atomic CAS done for
-  // insertion into the table. This is safe because each entry is at
-  // most updated once (from -1 to something else).
-  ZForwardingTableEntry entry = first(from_index, cursor);
-  while (!entry.is_empty()) {
-    if (entry.from_index() == from_index) {
-      // Match found, return matching entry
-      return entry;
-    }
-
-    entry = next(cursor);
-  }
-
-  // Match not found, return empty entry
-  return entry;
-}
-
-inline uintptr_t ZForwardingTable::insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingTableCursor* cursor) {
-  const ZForwardingTableEntry new_entry(from_index, to_offset);
-  const ZForwardingTableEntry old_entry; // empty
-
-  for (;;) {
-    const ZForwardingTableEntry prev_entry = Atomic::cmpxchg(new_entry, _table + *cursor, old_entry);
-    if (prev_entry.is_empty()) {
-      // Success
-      return to_offset;
-    }
-
-    // Find next empty or matching entry
-    ZForwardingTableEntry entry = at(cursor);
-    while (!entry.is_empty()) {
-      if (entry.from_index() == from_index) {
-        // Match found, return already inserted address
-        return entry.to_offset();
-      }
-
-      entry = next(cursor);
-    }
-  }
+inline ZForwarding* ZForwardingTable::get(uintptr_t addr) const {
+  return _map.get(addr);
 }
 
 #endif // SHARE_GC_Z_ZFORWARDINGTABLE_INLINE_HPP
--- a/src/hotspot/share/gc/z/zForwardingTableEntry.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * 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_ZFORWARDINGTABLEENTRY_HPP
-#define SHARE_GC_Z_ZFORWARDINGTABLEENTRY_HPP
-
-#include "gc/z/zBitField.hpp"
-#include "memory/allocation.hpp"
-#include "metaprogramming/primitiveConversions.hpp"
-
-//
-// Forwarding table entry layout
-// -----------------------------
-//
-//   6                      4 4                                             0
-//   3                      2 1                                             0
-//  +------------------------+-----------------------------------------------+
-//  |11111111 11111111 111111|11 11111111 11111111 11111111 11111111 11111111|
-//  +------------------------+-----------------------------------------------+
-//  |                        |
-//  |                        * 41-0 To Object Offset (42-bits)
-//  |
-//  * 63-42 From Object Index (22-bits)
-//
-
-class ZForwardingTableEntry {
-  friend struct PrimitiveConversions;
-
-private:
-  typedef ZBitField<uint64_t, size_t, 0,  42> field_to_offset;
-  typedef ZBitField<uint64_t, size_t, 42, 22> field_from_index;
-
-  uint64_t _entry;
-
-  static uintptr_t empty() {
-    return (uintptr_t)-1;
-  }
-
-public:
-  ZForwardingTableEntry() :
-      _entry(empty()) {}
-
-  ZForwardingTableEntry(size_t from_index, size_t to_offset) :
-      _entry(field_from_index::encode(from_index) |
-             field_to_offset::encode(to_offset)) {}
-
-  bool is_empty() const {
-    return _entry == empty();
-  }
-
-  size_t to_offset() const {
-    return field_to_offset::decode(_entry);
-  }
-
-  size_t from_index() const {
-    return field_from_index::decode(_entry);
-  }
-};
-
-// Needed to allow atomic operations on ZForwardingTableEntry
-template <>
-struct PrimitiveConversions::Translate<ZForwardingTableEntry> : public TrueType {
-  typedef ZForwardingTableEntry Value;
-  typedef uint64_t              Decayed;
-
-  static Decayed decay(Value v) {
-    return v._entry;
-  }
-
-  static Value recover(Decayed d) {
-    ZForwardingTableEntry entry;
-    entry._entry = d;
-    return entry;
-  }
-};
-
-#endif // SHARE_GC_Z_ZFORWARDINGTABLEENTRY_HPP
--- a/src/hotspot/share/gc/z/zGranuleMap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zGranuleMap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -46,6 +46,7 @@
 
   T get(uintptr_t addr) const;
   void put(uintptr_t addr, T value);
+  void put(uintptr_t addr, size_t size, T value);
 };
 
 template <typename T>
@@ -58,6 +59,7 @@
   ZGranuleMapIterator(const ZGranuleMap<T>* map);
 
   bool next(T* value);
+  bool next(T** value);
 };
 
 #endif // SHARE_GC_Z_ZGRANULEMAP_HPP
--- a/src/hotspot/share/gc/z/zGranuleMap.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zGranuleMap.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -66,6 +66,17 @@
 }
 
 template <typename T>
+inline void ZGranuleMap<T>::put(uintptr_t addr, size_t size, T value) {
+  assert(is_aligned(size, ZGranuleSize), "Misaligned");
+
+  const size_t start_index = index_for_addr(addr);
+  const size_t end_index = start_index + (size >> ZGranuleSizeShift);
+  for (size_t index = start_index; index < end_index; index++) {
+    _map[index] = value;
+  }
+}
+
+template <typename T>
 inline ZGranuleMapIterator<T>::ZGranuleMapIterator(const ZGranuleMap<T>* map) :
     _map(map),
     _next(0) {}
@@ -81,4 +92,15 @@
   return false;
 }
 
+template <typename T>
+inline bool ZGranuleMapIterator<T>::next(T** value) {
+  if (_next < _map->size()) {
+    *value = _map->_map + _next++;
+    return true;
+  }
+
+  // End of map
+  return false;
+}
+
 #endif // SHARE_GC_Z_ZGRANULEMAP_INLINE_HPP
--- a/src/hotspot/share/gc/z/zHeap.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zHeap.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -63,8 +63,9 @@
     _workers(),
     _object_allocator(_workers.nworkers()),
     _page_allocator(heap_min_size(), heap_max_size(), heap_max_reserve_size()),
-    _pagetable(),
-    _mark(&_workers, &_pagetable),
+    _page_table(),
+    _forwarding_table(),
+    _mark(&_workers, &_page_table),
     _reference_processor(&_workers),
     _weak_roots_processor(&_workers),
     _relocate(&_workers),
@@ -172,7 +173,7 @@
     return false;
   }
 
-  const ZPage* const page = _pagetable.get(addr);
+  const ZPage* const page = _page_table.get(addr);
   if (page != NULL) {
     return page->is_in(addr);
   }
@@ -181,12 +182,12 @@
 }
 
 uintptr_t ZHeap::block_start(uintptr_t addr) const {
-  const ZPage* const page = _pagetable.get(addr);
+  const ZPage* const page = _page_table.get(addr);
   return page->block_start(addr);
 }
 
 bool ZHeap::block_is_obj(uintptr_t addr) const {
-  const ZPage* const page = _pagetable.get(addr);
+  const ZPage* const page = _page_table.get(addr);
   return page->block_is_obj(addr);
 }
 
@@ -220,8 +221,8 @@
 ZPage* ZHeap::alloc_page(uint8_t type, size_t size, ZAllocationFlags flags) {
   ZPage* const page = _page_allocator.alloc_page(type, size, flags);
   if (page != NULL) {
-    // Update pagetable
-    _pagetable.insert(page);
+    // Insert page table entry
+    _page_table.insert(page);
   }
 
   return page;
@@ -234,33 +235,44 @@
   log_trace(gc)("Undo page allocation, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT ", size: " SIZE_FORMAT,
                 ZThread::id(), ZThread::name(), p2i(page), page->size());
 
-  release_page(page, false /* reclaimed */);
+  free_page(page, false /* reclaimed */);
 }
 
-bool ZHeap::retain_page(ZPage* page) {
-  return page->inc_refcount();
+void ZHeap::free_page(ZPage* page, bool reclaimed) {
+  // Remove page table entry
+  _page_table.remove(page);
+
+  // Free page
+  _page_allocator.free_page(page, reclaimed);
 }
 
-void ZHeap::release_page(ZPage* page, bool reclaimed) {
-  if (page->dec_refcount()) {
-    _page_allocator.free_page(page, reclaimed);
+void ZHeap::before_flip() {
+  if (ZVerifyViews) {
+    // Unmap all pages
+    _page_allocator.unmap_all_pages();
   }
 }
 
-void ZHeap::flip_views() {
-  // For debugging only
-  if (ZUnmapBadViews) {
-    // Flip pages
-    ZPageTableIterator iter(&_pagetable);
+void ZHeap::after_flip() {
+  if (ZVerifyViews) {
+    // Map all pages
+    ZPageTableIterator iter(&_page_table);
     for (ZPage* page; iter.next(&page);) {
-      if (!page->is_detached()) {
-        _page_allocator.flip_page(page);
-      }
+      _page_allocator.map_page(page);
     }
+  }
+}
 
-    // Flip pre-mapped memory
-    _page_allocator.flip_pre_mapped();
-  }
+void ZHeap::flip_to_marked() {
+  before_flip();
+  ZAddressMasks::flip_to_marked();
+  after_flip();
+}
+
+void ZHeap::flip_to_remapped() {
+  before_flip();
+  ZAddressMasks::flip_to_remapped();
+  after_flip();
 }
 
 void ZHeap::mark_start() {
@@ -270,8 +282,7 @@
   ZStatSample(ZSamplerHeapUsedBeforeMark, used());
 
   // Flip address view
-  ZAddressMasks::flip_to_marked();
-  flip_views();
+  flip_to_marked();
 
   // Retire allocating pages
   _object_allocator.retire_pages();
@@ -391,25 +402,14 @@
   _reference_processor.enqueue_references();
 }
 
-void ZHeap::destroy_detached_pages() {
-  ZList<ZPage> list;
-
-  _page_allocator.flush_detached_pages(&list);
+void ZHeap::select_relocation_set() {
+  // Do not allow pages to be deleted
+  _page_allocator.enable_deferred_delete();
 
-  for (ZPage* page = list.remove_first(); page != NULL; page = list.remove_first()) {
-    // Remove pagetable entry
-    _pagetable.remove(page);
-
-    // Delete the page
-    _page_allocator.destroy_page(page);
-  }
-}
-
-void ZHeap::select_relocation_set() {
   // Register relocatable pages with selector
   ZRelocationSetSelector selector;
-  ZPageTableIterator iter(&_pagetable);
-  for (ZPage* page; iter.next(&page);) {
+  ZPageTableIterator pt_iter(&_page_table);
+  for (ZPage* page; pt_iter.next(&page);) {
     if (!page->is_relocatable()) {
       // Not relocatable, don't register
       continue;
@@ -423,13 +423,22 @@
       selector.register_garbage_page(page);
 
       // Reclaim page immediately
-      release_page(page, true /* reclaimed */);
+      free_page(page, true /* reclaimed */);
     }
   }
 
+  // Allow pages to be deleted
+  _page_allocator.disable_deferred_delete();
+
   // Select pages to relocate
   selector.select(&_relocation_set);
 
+  // Setup forwarding table
+  ZRelocationSetIterator rs_iter(&_relocation_set);
+  for (ZForwarding* forwarding; rs_iter.next(&forwarding);) {
+    _forwarding_table.insert(forwarding);
+  }
+
   // Update statistics
   ZStatRelocation::set_at_select_relocation_set(selector.relocating());
   ZStatHeap::set_at_select_relocation_set(selector.live(),
@@ -437,26 +446,15 @@
                                           reclaimed());
 }
 
-void ZHeap::prepare_relocation_set() {
+void ZHeap::reset_relocation_set() {
+  // Reset forwarding table
   ZRelocationSetIterator iter(&_relocation_set);
-  for (ZPage* page; iter.next(&page);) {
-    // Prepare for relocation
-    page->set_forwarding();
-
-    // Update pagetable
-    _pagetable.set_relocating(page);
+  for (ZForwarding* forwarding; iter.next(&forwarding);) {
+    _forwarding_table.remove(forwarding);
   }
-}
 
-void ZHeap::reset_relocation_set() {
-  ZRelocationSetIterator iter(&_relocation_set);
-  for (ZPage* page; iter.next(&page);) {
-    // Reset relocation information
-    page->reset_forwarding();
-
-    // Update pagetable
-    _pagetable.clear_relocating(page);
-  }
+  // Reset relocation set
+  _relocation_set.reset();
 }
 
 void ZHeap::relocate_start() {
@@ -466,8 +464,7 @@
   _unload.finish();
 
   // Flip address view
-  ZAddressMasks::flip_to_remapped();
-  flip_views();
+  flip_to_remapped();
 
   // Enter relocate phase
   ZGlobalPhase = ZPhaseRelocate;
@@ -480,25 +477,6 @@
   _relocate.start();
 }
 
-uintptr_t ZHeap::relocate_object(uintptr_t addr) {
-  assert(ZGlobalPhase == ZPhaseRelocate, "Relocate not allowed");
-  ZPage* const page = _pagetable.get(addr);
-  const bool retained = retain_page(page);
-  const uintptr_t new_addr = page->relocate_object(addr);
-  if (retained) {
-    release_page(page, true /* reclaimed */);
-  }
-
-  return new_addr;
-}
-
-uintptr_t ZHeap::forward_object(uintptr_t addr) {
-  assert(ZGlobalPhase == ZPhaseMark ||
-         ZGlobalPhase == ZPhaseMarkCompleted, "Forward not allowed");
-  ZPage* const page = _pagetable.get(addr);
-  return page->forward_object(addr);
-}
-
 void ZHeap::relocate() {
   // Relocate relocation set
   const bool success = _relocate.relocate(&_relocation_set);
@@ -545,11 +523,18 @@
   print_on(st);
   st->cr();
 
-  ZPageTableIterator iter(&_pagetable);
+  // Do not allow pages to be deleted
+  _page_allocator.enable_deferred_delete();
+
+  // Print all pages
+  ZPageTableIterator iter(&_page_table);
   for (ZPage* page; iter.next(&page);) {
     page->print_on(st);
   }
 
+  // Allow pages to be deleted
+  _page_allocator.enable_deferred_delete();
+
   st->cr();
 }
 
--- a/src/hotspot/share/gc/z/zHeap.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zHeap.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 #include "gc/shared/gcTimer.hpp"
 #include "gc/z/zAllocationFlags.hpp"
 #include "gc/z/zArray.hpp"
+#include "gc/z/zForwardingTable.hpp"
 #include "gc/z/zList.hpp"
 #include "gc/z/zLock.hpp"
 #include "gc/z/zMark.hpp"
@@ -54,7 +55,8 @@
   ZWorkers            _workers;
   ZObjectAllocator    _object_allocator;
   ZPageAllocator      _page_allocator;
-  ZPageTable          _pagetable;
+  ZPageTable          _page_table;
+  ZForwardingTable    _forwarding_table;
   ZMark               _mark;
   ZReferenceProcessor _reference_processor;
   ZWeakRootsProcessor _weak_roots_processor;
@@ -67,8 +69,13 @@
   size_t heap_max_size() const;
   size_t heap_max_reserve_size() const;
 
+  void before_flip();
+  void after_flip();
+
+  void flip_to_marked();
+  void flip_to_remapped();
+
   void out_of_memory();
-  void flip_views();
   void fixup_partial_loads();
 
 public:
@@ -118,8 +125,7 @@
   // Page allocation
   ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags);
   void undo_alloc_page(ZPage* page);
-  bool retain_page(ZPage* page);
-  void release_page(ZPage* page, bool reclaimed);
+  void free_page(ZPage* page, bool reclaimed);
 
   // Object allocation
   uintptr_t alloc_tlab(size_t size);
@@ -138,19 +144,14 @@
   void mark_flush_and_free(Thread* thread);
   bool mark_end();
 
-  // Post-marking & Pre-relocation
-  void destroy_detached_pages();
-
   // Relocation set
   void select_relocation_set();
-  void prepare_relocation_set();
   void reset_relocation_set();
 
   // Relocation
-  bool is_relocating(uintptr_t addr) const;
   void relocate_start();
   uintptr_t relocate_object(uintptr_t addr);
-  uintptr_t forward_object(uintptr_t addr);
+  uintptr_t remap_object(uintptr_t addr);
   void relocate();
 
   // Iteration
--- a/src/hotspot/share/gc/z/zHeap.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zHeap.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 #define SHARE_GC_Z_ZHEAP_INLINE_HPP
 
 #include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
+#include "gc/z/zForwardingTable.inline.hpp"
 #include "gc/z/zHeap.hpp"
 #include "gc/z/zMark.inline.hpp"
 #include "gc/z/zOop.inline.hpp"
@@ -42,17 +44,13 @@
   return &_reference_processor;
 }
 
-inline bool ZHeap::is_relocating(uintptr_t addr) const {
-  return _pagetable.is_relocating(addr);
-}
-
 inline bool ZHeap::is_object_live(uintptr_t addr) const {
-  ZPage* page = _pagetable.get(addr);
+  ZPage* page = _page_table.get(addr);
   return page->is_object_live(addr);
 }
 
 inline bool ZHeap::is_object_strongly_live(uintptr_t addr) const {
-  ZPage* page = _pagetable.get(addr);
+  ZPage* page = _page_table.get(addr);
   return page->is_object_strongly_live(addr);
 }
 
@@ -85,10 +83,43 @@
 }
 
 inline void ZHeap::undo_alloc_object_for_relocation(uintptr_t addr, size_t size) {
-  ZPage* const page = _pagetable.get(addr);
+  ZPage* const page = _page_table.get(addr);
   _object_allocator.undo_alloc_object_for_relocation(page, addr, size);
 }
 
+inline uintptr_t ZHeap::relocate_object(uintptr_t addr) {
+  assert(ZGlobalPhase == ZPhaseRelocate, "Relocate not allowed");
+
+  ZForwarding* const forwarding = _forwarding_table.get(addr);
+  if (forwarding == NULL) {
+    // Not forwarding
+    return ZAddress::good(addr);
+  }
+
+  // Relocate object
+  const bool retained = forwarding->retain_page();
+  const uintptr_t new_addr = _relocate.relocate_object(forwarding, addr);
+  if (retained) {
+    forwarding->release_page();
+  }
+
+  return new_addr;
+}
+
+inline uintptr_t ZHeap::remap_object(uintptr_t addr) {
+  assert(ZGlobalPhase == ZPhaseMark ||
+         ZGlobalPhase == ZPhaseMarkCompleted, "Forward not allowed");
+
+  ZForwarding* const forwarding = _forwarding_table.get(addr);
+  if (forwarding == NULL) {
+    // Not forwarding
+    return ZAddress::good(addr);
+  }
+
+  // Forward object
+  return _relocate.forward_object(forwarding, addr);
+}
+
 inline bool ZHeap::is_alloc_stalled() const {
   return _page_allocator.is_alloc_stalled();
 }
--- a/src/hotspot/share/gc/z/zMark.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zMark.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -56,9 +56,9 @@
 static const ZStatSubPhase ZSubPhaseConcurrentMarkTryTerminate("Concurrent Mark Try Terminate");
 static const ZStatSubPhase ZSubPhaseMarkTryComplete("Pause Mark Try Complete");
 
-ZMark::ZMark(ZWorkers* workers, ZPageTable* pagetable) :
+ZMark::ZMark(ZWorkers* workers, ZPageTable* page_table) :
     _workers(workers),
-    _pagetable(pagetable),
+    _page_table(page_table),
     _allocator(),
     _stripes(),
     _terminate(),
@@ -307,7 +307,7 @@
 }
 
 bool ZMark::try_mark_object(ZMarkCache* cache, uintptr_t addr, bool finalizable) {
-  ZPage* const page = _pagetable->get(addr);
+  ZPage* const page = _page_table->get(addr);
   if (page->is_allocating()) {
     // Newly allocated objects are implicitly marked
     return false;
--- a/src/hotspot/share/gc/z/zMark.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zMark.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -42,7 +42,7 @@
 
 private:
   ZWorkers* const     _workers;
-  ZPageTable* const   _pagetable;
+  ZPageTable* const   _page_table;
   ZMarkStackAllocator _allocator;
   ZMarkStripeSet      _stripes;
   ZMarkTerminate      _terminate;
@@ -101,7 +101,7 @@
   void verify_all_stacks_empty() const;
 
 public:
-  ZMark(ZWorkers* workers, ZPageTable* pagetable);
+  ZMark(ZWorkers* workers, ZPageTable* page_table);
 
   bool is_initialized() const;
 
--- a/src/hotspot/share/gc/z/zNMethodAllocator.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zArray.inline.hpp"
-#include "gc/z/zNMethodAllocator.hpp"
-#include "memory/allocation.hpp"
-
-ZArray<void*> ZNMethodAllocator::_deferred_frees;
-bool          ZNMethodAllocator::_defer_frees(false);
-
-void ZNMethodAllocator::immediate_free(void* data) {
-  FREE_C_HEAP_ARRAY(uint8_t, data);
-}
-
-void ZNMethodAllocator::deferred_free(void* data) {
-  _deferred_frees.add(data);
-}
-
-void* ZNMethodAllocator::allocate(size_t size) {
-  return NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
-}
-
-void ZNMethodAllocator::free(void* data) {
-  if (data == NULL) {
-    return;
-  }
-
-  if (_defer_frees) {
-    deferred_free(data);
-  } else {
-    immediate_free(data);
-  }
-}
-
-void ZNMethodAllocator::activate_deferred_frees() {
-  assert(_deferred_frees.is_empty(), "precondition");
-  _defer_frees = true;
-}
-
-void ZNMethodAllocator::deactivate_and_process_deferred_frees() {
-  _defer_frees = false;
-
-  ZArrayIterator<void*> iter(&_deferred_frees);
-  for (void* data; iter.next(&data);) {
-    immediate_free(data);
-  }
-  _deferred_frees.clear();
-}
--- a/src/hotspot/share/gc/z/zNMethodAllocator.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
-#define SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
-
-#include "memory/allocation.hpp"
-#include "gc/z/zArray.hpp"
-
-class ZNMethodAllocator : public AllStatic {
-private:
-  static ZArray<void*> _deferred_frees;
-  static bool          _defer_frees;
-
-  static void immediate_free(void* data);
-  static void deferred_free(void* data);
-
-public:
-  static void* allocate(size_t size);
-  static void free(void* data);
-
-  static void activate_deferred_frees();
-  static void deactivate_and_process_deferred_frees();
-};
-
-#endif // SHARE_GC_Z_ZNMETHODALLOCATOR_HPP
--- a/src/hotspot/share/gc/z/zNMethodData.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zNMethodData.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -22,6 +22,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/z/zAttachedArray.inline.hpp"
 #include "gc/z/zLock.inline.hpp"
 #include "gc/z/zNMethodData.hpp"
 #include "memory/allocation.hpp"
@@ -31,40 +32,29 @@
 #include "utilities/debug.hpp"
 #include "utilities/growableArray.hpp"
 
-size_t ZNMethodDataOops::header_size() {
-  const size_t size = sizeof(ZNMethodDataOops);
-  assert(is_aligned(size, sizeof(oop*)), "Header misaligned");
-  return size;
-}
-
 ZNMethodDataOops* ZNMethodDataOops::create(const GrowableArray<oop*>& immediates, bool has_non_immediates) {
-  // Allocate memory for the ZNMethodDataOops object
-  // plus the immediate oop* array that follows right after.
-  const size_t size = ZNMethodDataOops::header_size() + (sizeof(oop*) * immediates.length());
-  void* const mem = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
-  return ::new (mem) ZNMethodDataOops(immediates, has_non_immediates);
+  return ::new (AttachedArray::alloc(immediates.length())) ZNMethodDataOops(immediates, has_non_immediates);
 }
 
 void ZNMethodDataOops::destroy(ZNMethodDataOops* oops) {
-  FREE_C_HEAP_ARRAY(uint8_t, oops);
+  AttachedArray::free(oops);
 }
 
 ZNMethodDataOops::ZNMethodDataOops(const GrowableArray<oop*>& immediates, bool has_non_immediates) :
-    _nimmediates(immediates.length()),
+    _immediates(immediates.length()),
     _has_non_immediates(has_non_immediates) {
   // Save all immediate oops
-  for (size_t i = 0; i < _nimmediates; i++) {
+  for (size_t i = 0; i < immediates_count(); i++) {
     immediates_begin()[i] = immediates.at(i);
   }
 }
 
 size_t ZNMethodDataOops::immediates_count() const {
-  return _nimmediates;
+  return _immediates.length();
 }
 
 oop** ZNMethodDataOops::immediates_begin() const {
-  // The immediate oop* array starts immediately after this object
-  return (oop**)((uintptr_t)this + header_size());
+  return _immediates(this);
 }
 
 oop** ZNMethodDataOops::immediates_end() const {
--- a/src/hotspot/share/gc/z/zNMethodData.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zNMethodData.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -21,23 +21,24 @@
  * questions.
  */
 
+#ifndef SHARE_GC_Z_ZNMETHODDATA_HPP
+#define SHARE_GC_Z_ZNMETHODDATA_HPP
+
+#include "gc/z/zAttachedArray.hpp"
 #include "gc/z/zLock.hpp"
 #include "memory/allocation.hpp"
 #include "oops/oopsHierarchy.hpp"
 #include "utilities/globalDefinitions.hpp"
 
-#ifndef SHARE_GC_Z_ZNMETHODDATA_HPP
-#define SHARE_GC_Z_ZNMETHODDATA_HPP
-
 class nmethod;
 template <typename T> class GrowableArray;
 
 class ZNMethodDataOops {
 private:
-  const size_t _nimmediates;
-  bool         _has_non_immediates;
+  typedef ZAttachedArray<ZNMethodDataOops, oop*> AttachedArray;
 
-  static size_t header_size();
+  const AttachedArray _immediates;
+  const bool          _has_non_immediates;
 
   ZNMethodDataOops(const GrowableArray<oop*>& immediates, bool has_non_immediates);
 
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zNMethodTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -30,12 +30,12 @@
 #include "gc/z/zGlobals.hpp"
 #include "gc/z/zHash.inline.hpp"
 #include "gc/z/zLock.inline.hpp"
-#include "gc/z/zNMethodAllocator.hpp"
 #include "gc/z/zNMethodData.hpp"
 #include "gc/z/zNMethodTable.hpp"
 #include "gc/z/zNMethodTableEntry.hpp"
 #include "gc/z/zNMethodTableIteration.hpp"
 #include "gc/z/zOopClosures.inline.hpp"
+#include "gc/z/zSafeDelete.inline.hpp"
 #include "gc/z/zTask.hpp"
 #include "gc/z/zWorkers.hpp"
 #include "logging/log.hpp"
@@ -51,15 +51,7 @@
 size_t ZNMethodTable::_nregistered = 0;
 size_t ZNMethodTable::_nunregistered = 0;
 ZNMethodTableIteration ZNMethodTable::_iteration;
-
-ZNMethodTableEntry* ZNMethodTable::create(size_t size) {
-  void* const mem = ZNMethodAllocator::allocate(size * sizeof(ZNMethodTableEntry));
-  return ::new (mem) ZNMethodTableEntry[size];
-}
-
-void ZNMethodTable::destroy(ZNMethodTableEntry* table) {
-  ZNMethodAllocator::free(table);
-}
+ZSafeDelete<ZNMethodTableEntry[]> ZNMethodTable::_safe_delete;
 
 size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) {
   assert(is_power_of_2(size), "Invalid size");
@@ -128,7 +120,7 @@
                          _nunregistered, percent_of(_nunregistered, _size), 0.0);
 
   // Allocate new table
-  ZNMethodTableEntry* const new_table = ZNMethodTable::create(new_size);
+  ZNMethodTableEntry* const new_table = new ZNMethodTableEntry[new_size];
 
   // Transfer all registered entries
   for (size_t i = 0; i < _size; i++) {
@@ -139,7 +131,7 @@
   }
 
   // Free old table
-  ZNMethodTable::destroy(_table);
+  _safe_delete(_table);
 
   // Install new table
   _table = new_table;
@@ -219,8 +211,8 @@
 void ZNMethodTable::nmethods_do_begin() {
   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
 
-  // Make sure we don't free data while iterating
-  ZNMethodAllocator::activate_deferred_frees();
+  // Do not allow the table to be deleted while iterating
+  _safe_delete.enable_deferred_delete();
 
   // Prepare iteration
   _iteration.nmethods_do_begin(_table, _size);
@@ -232,8 +224,8 @@
   // Finish iteration
   _iteration.nmethods_do_end();
 
-  // Process deferred frees
-  ZNMethodAllocator::deactivate_and_process_deferred_frees();
+  // Allow the table to be deleted
+  _safe_delete.disable_deferred_delete();
 
   // Notify iteration done
   CodeCache_lock->notify_all();
--- a/src/hotspot/share/gc/z/zNMethodTable.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zNMethodTable.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -25,6 +25,7 @@
 #define SHARE_GC_Z_ZNMETHODTABLE_HPP
 
 #include "gc/z/zNMethodTableIteration.hpp"
+#include "gc/z/zSafeDelete.hpp"
 #include "memory/allocation.hpp"
 
 class nmethod;
@@ -34,11 +35,12 @@
 
 class ZNMethodTable : public AllStatic {
 private:
-  static ZNMethodTableEntry*    _table;
-  static size_t                 _size;
-  static size_t                 _nregistered;
-  static size_t                 _nunregistered;
-  static ZNMethodTableIteration _iteration;
+  static ZNMethodTableEntry*               _table;
+  static size_t                            _size;
+  static size_t                            _nregistered;
+  static size_t                            _nunregistered;
+  static ZNMethodTableIteration            _iteration;
+  static ZSafeDelete<ZNMethodTableEntry[]> _safe_delete;
 
   static ZNMethodTableEntry* create(size_t size);
   static void destroy(ZNMethodTableEntry* table);
--- a/src/hotspot/share/gc/z/zObjectAllocator.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zObjectAllocator.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -186,10 +186,6 @@
   ZAllocationFlags flags;
   flags.set_no_reserve();
 
-  if (!ZStallOnOutOfMemory) {
-    flags.set_non_blocking();
-  }
-
   return alloc_object(size, flags);
 }
 
--- a/src/hotspot/share/gc/z/zPage.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPage.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -22,35 +22,19 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "gc/z/zAddress.inline.hpp"
-#include "gc/z/zForwardingTable.inline.hpp"
-#include "gc/z/zHeap.inline.hpp"
-#include "gc/z/zLiveMap.inline.hpp"
-#include "gc/z/zMark.hpp"
 #include "gc/z/zPage.inline.hpp"
 #include "gc/z/zPhysicalMemory.inline.hpp"
-#include "gc/z/zStat.hpp"
-#include "gc/z/zThread.hpp"
-#include "gc/z/zUtils.inline.hpp"
-#include "logging/log.hpp"
-#include "runtime/orderAccess.hpp"
+#include "gc/z/zVirtualMemory.inline.hpp"
 #include "utilities/align.hpp"
 #include "utilities/debug.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-static const ZStatCounter ZCounterRelocationContention("Contention", "Relocation Contention", ZStatUnitOpsPerSecond);
 
 ZPage::ZPage(uint8_t type, ZVirtualMemory vmem, ZPhysicalMemory pmem) :
     _type(type),
-    _pinned(0),
     _numa_id((uint8_t)-1),
     _seqnum(0),
     _virtual(vmem),
     _top(start()),
     _livemap(object_max_count()),
-    _refcount(0),
-    _forwarding(),
     _physical(pmem) {
   assert(!_physical.is_null(), "Should not be null");
   assert(!_virtual.is_null(), "Should not be null");
@@ -61,111 +45,20 @@
 }
 
 ZPage::~ZPage() {
-  assert(!is_active(), "Should not be active");
-  assert(is_detached(), "Should be detached");
+  assert(_physical.is_null(), "Should be null");
 }
 
 void ZPage::reset() {
-  assert(!is_active(), "Should not be active");
-  assert(!is_pinned(), "Should not be pinned");
-  assert(!is_detached(), "Should not be detached");
-
   _seqnum = ZGlobalSeqNum;
   _top = start();
   _livemap.reset();
-
-  // Make sure we don't make the page active before
-  // the reset of the above fields are visible.
-  OrderAccess::storestore();
-
-  _refcount = 1;
-}
-
-uintptr_t ZPage::relocate_object_inner(uintptr_t from_index, uintptr_t from_offset) {
-  ZForwardingTableCursor cursor;
-
-  // Lookup address in forwarding table
-  const ZForwardingTableEntry entry = _forwarding.find(from_index, &cursor);
-  if (entry.from_index() == from_index) {
-    // Already relocated, return new address
-    return entry.to_offset();
-  }
-
-  // Not found in forwarding table, relocate object
-  assert(is_object_marked(from_offset), "Should be marked");
-
-  if (is_pinned()) {
-    // In-place forward
-    return _forwarding.insert(from_index, from_offset, &cursor);
-  }
-
-  // Allocate object
-  const uintptr_t from_good = ZAddress::good(from_offset);
-  const size_t size = ZUtils::object_size(from_good);
-  const uintptr_t to_good = ZHeap::heap()->alloc_object_for_relocation(size);
-  if (to_good == 0) {
-    // Failed, in-place forward
-    return _forwarding.insert(from_index, from_offset, &cursor);
-  }
-
-  // Copy object
-  ZUtils::object_copy(from_good, to_good, size);
-
-  // Update forwarding table
-  const uintptr_t to_offset = ZAddress::offset(to_good);
-  const uintptr_t to_offset_final = _forwarding.insert(from_index, to_offset, &cursor);
-  if (to_offset_final == to_offset) {
-    // Relocation succeeded
-    return to_offset;
-  }
-
-  // Relocation contention
-  ZStatInc(ZCounterRelocationContention);
-  log_trace(gc)("Relocation contention, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT
-                ", entry: " SIZE_FORMAT ", oop: " PTR_FORMAT ", size: " SIZE_FORMAT,
-                ZThread::id(), ZThread::name(), p2i(this), cursor, from_good, size);
-
-  // Try undo allocation
-  ZHeap::heap()->undo_alloc_object_for_relocation(to_good, size);
-
-  return to_offset_final;
-}
-
-uintptr_t ZPage::relocate_object(uintptr_t from) {
-  assert(ZHeap::heap()->is_relocating(from), "Should be relocating");
-
-  const uintptr_t from_offset = ZAddress::offset(from);
-  const uintptr_t from_index = (from_offset - start()) >> object_alignment_shift();
-  const uintptr_t to_offset = relocate_object_inner(from_index, from_offset);
-  if (from_offset == to_offset) {
-    // In-place forwarding, pin page
-    set_pinned();
-  }
-
-  return ZAddress::good(to_offset);
-}
-
-uintptr_t ZPage::forward_object(uintptr_t from) {
-  assert(ZHeap::heap()->is_relocating(from), "Should be relocated");
-
-  // Lookup address in forwarding table
-  const uintptr_t from_offset = ZAddress::offset(from);
-  const uintptr_t from_index = (from_offset - start()) >> object_alignment_shift();
-  const ZForwardingTableEntry entry = _forwarding.find(from_index);
-  assert(entry.from_index() == from_index, "Should be forwarded");
-
-  return ZAddress::good(entry.to_offset());
 }
 
 void ZPage::print_on(outputStream* out) const {
-  out->print_cr(" %-6s  " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " %s%s%s%s%s%s",
+  out->print_cr(" %-6s  " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " %s%s",
                 type_to_string(), start(), top(), end(),
                 is_allocating()  ? " Allocating"  : "",
-                is_relocatable() ? " Relocatable" : "",
-                is_forwarding()  ? " Forwarding"  : "",
-                is_pinned()      ? " Pinned"      : "",
-                is_detached()    ? " Detached"    : "",
-                !is_active()     ? " Inactive"    : "");
+                is_relocatable() ? " Relocatable" : "");
 }
 
 void ZPage::print() const {
--- a/src/hotspot/share/gc/z/zPage.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPage.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,6 @@
 #ifndef SHARE_GC_Z_ZPAGE_HPP
 #define SHARE_GC_Z_ZPAGE_HPP
 
-#include "gc/z/zForwardingTable.hpp"
 #include "gc/z/zList.hpp"
 #include "gc/z/zLiveMap.hpp"
 #include "gc/z/zPhysicalMemory.hpp"
@@ -38,7 +37,6 @@
 private:
   // Always hot
   const uint8_t        _type;             // Page type
-  volatile uint8_t     _pinned;           // Pinned flag
   uint8_t              _numa_id;          // NUMA node affinity
   uint32_t             _seqnum;           // Allocation sequence number
   const ZVirtualMemory _virtual;          // Virtual start/end address
@@ -46,14 +44,10 @@
   ZLiveMap             _livemap;          // Live map
 
   // Hot when relocated and cached
-  volatile uint32_t    _refcount;         // Page reference count
-  ZForwardingTable     _forwarding;       // Forwarding table
   ZPhysicalMemory      _physical;         // Physical memory for page
   ZListNode<ZPage>     _node;             // Page list node
 
   const char* type_to_string() const;
-  uint32_t object_max_count() const;
-  uintptr_t relocate_object_inner(uintptr_t from_index, uintptr_t from_offset);
 
   bool is_object_marked(uintptr_t addr) const;
   bool is_object_strongly_marked(uintptr_t addr) const;
@@ -62,6 +56,7 @@
   ZPage(uint8_t type, ZVirtualMemory vmem, ZPhysicalMemory pmem);
   ~ZPage();
 
+  uint32_t object_max_count() const;
   size_t object_alignment_shift() const;
   size_t object_alignment() const;
 
@@ -79,36 +74,24 @@
 
   void reset();
 
-  bool inc_refcount();
-  bool dec_refcount();
-
   bool is_in(uintptr_t addr) const;
 
   uintptr_t block_start(uintptr_t addr) const;
   bool block_is_obj(uintptr_t addr) const;
 
-  bool is_active() const;
   bool is_allocating() const;
   bool is_relocatable() const;
-  bool is_detached() const;
 
   bool is_mapped() const;
   void set_pre_mapped();
 
-  bool is_pinned() const;
-  void set_pinned();
-
-  bool is_forwarding() const;
-  void set_forwarding();
-  void reset_forwarding();
-  void verify_forwarding() const;
-
   bool is_marked() const;
   bool is_object_live(uintptr_t addr) const;
   bool is_object_strongly_live(uintptr_t addr) const;
   bool mark_object(uintptr_t addr, bool finalizable, bool& inc_live);
 
   void inc_live_atomic(uint32_t objects, size_t bytes);
+  uint32_t live_objects() const;
   size_t live_bytes() const;
 
   void object_iterate(ObjectClosure* cl);
@@ -119,9 +102,6 @@
   bool undo_alloc_object(uintptr_t addr, size_t size);
   bool undo_alloc_object_atomic(uintptr_t addr, size_t size);
 
-  uintptr_t relocate_object(uintptr_t from);
-  uintptr_t forward_object(uintptr_t from);
-
   void print_on(outputStream* out) const;
   void print() const;
 };
--- a/src/hotspot/share/gc/z/zPage.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPage.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,6 @@
 #define SHARE_GC_Z_ZPAGE_INLINE_HPP
 
 #include "gc/z/zAddress.inline.hpp"
-#include "gc/z/zForwardingTable.inline.hpp"
 #include "gc/z/zGlobals.hpp"
 #include "gc/z/zLiveMap.inline.hpp"
 #include "gc/z/zMark.hpp"
@@ -35,6 +34,7 @@
 #include "gc/z/zVirtualMemory.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
 #include "utilities/align.hpp"
 #include "utilities/debug.hpp"
 
@@ -132,20 +132,6 @@
   return _numa_id;
 }
 
-inline bool ZPage::inc_refcount() {
-  for (uint32_t prev_refcount = _refcount; prev_refcount > 0; prev_refcount = _refcount) {
-    if (Atomic::cmpxchg(prev_refcount + 1, &_refcount, prev_refcount) == prev_refcount) {
-      return true;
-    }
-  }
-  return false;
-}
-
-inline bool ZPage::dec_refcount() {
-  assert(is_active(), "Should be active");
-  return Atomic::sub(1u, &_refcount) == 0;
-}
-
 inline bool ZPage::is_in(uintptr_t addr) const {
   const uintptr_t offset = ZAddress::offset(addr);
   return offset >= start() && offset < top();
@@ -163,20 +149,12 @@
   return ZAddress::offset(addr) < top();
 }
 
-inline bool ZPage::is_active() const {
-  return _refcount > 0;
-}
-
 inline bool ZPage::is_allocating() const {
-  return is_active() && _seqnum == ZGlobalSeqNum;
+  return _seqnum == ZGlobalSeqNum;
 }
 
 inline bool ZPage::is_relocatable() const {
-  return is_active() && _seqnum < ZGlobalSeqNum;
-}
-
-inline bool ZPage::is_detached() const {
-  return _physical.is_null();
+  return _seqnum < ZGlobalSeqNum;
 }
 
 inline bool ZPage::is_mapped() const {
@@ -190,32 +168,6 @@
   _seqnum = 1;
 }
 
-inline bool ZPage::is_pinned() const {
-  return _pinned;
-}
-
-inline void ZPage::set_pinned() {
-  _pinned = 1;
-}
-
-inline bool ZPage::is_forwarding() const {
-  return !_forwarding.is_null();
-}
-
-inline void ZPage::set_forwarding() {
-  assert(is_marked(), "Should be marked");
-  _forwarding.setup(_livemap.live_objects());
-}
-
-inline void ZPage::reset_forwarding() {
-  _forwarding.reset();
-  _pinned = 0;
-}
-
-inline void ZPage::verify_forwarding() const {
-  _forwarding.verify(object_max_count(), _livemap.live_objects());
-}
-
 inline bool ZPage::is_marked() const {
   assert(is_relocatable(), "Invalid page state");
   return _livemap.is_marked();
@@ -253,6 +205,11 @@
   _livemap.inc_live_atomic(objects, bytes);
 }
 
+inline uint32_t ZPage::live_objects() const {
+  assert(is_marked(), "Should be marked");
+  return _livemap.live_objects();
+}
+
 inline size_t ZPage::live_bytes() const {
   assert(is_marked(), "Should be marked");
   return _livemap.live_bytes();
--- a/src/hotspot/share/gc/z/zPageAllocator.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPageAllocator.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -31,6 +31,7 @@
 #include "gc/z/zPageAllocator.hpp"
 #include "gc/z/zPageCache.inline.hpp"
 #include "gc/z/zPreMappedMemory.inline.hpp"
+#include "gc/z/zSafeDelete.inline.hpp"
 #include "gc/z/zStat.hpp"
 #include "gc/z/zTracer.inline.hpp"
 #include "runtime/init.hpp"
@@ -96,7 +97,7 @@
     _allocated(0),
     _reclaimed(0),
     _queue(),
-    _detached() {}
+    _safe_delete() {}
 
 bool ZPageAllocator::is_initialized() const {
   return _physical.is_initialized() &&
@@ -242,34 +243,27 @@
   _pre_mapped.clear();
 }
 
-void ZPageAllocator::map_page(ZPage* page) {
-  // Map physical memory
-  _physical.map(page->physical_memory(), page->start());
-}
-
-void ZPageAllocator::detach_page(ZPage* page) {
-  // Detach the memory mapping.
+void ZPageAllocator::destroy_page(ZPage* page) {
+  // Detach virtual and physical memory
   detach_memory(page->virtual_memory(), page->physical_memory());
 
-  // Add to list of detached pages
-  _detached.insert_last(page);
+  // Delete page safely
+  _safe_delete(page);
 }
 
-void ZPageAllocator::destroy_page(ZPage* page) {
-  assert(page->is_detached(), "Invalid page state");
-
-  // Free virtual memory
-  {
-    ZLocker<ZLock> locker(&_lock);
-    _virtual.free(page->virtual_memory());
+void ZPageAllocator::map_page(ZPage* page) {
+  // Map physical memory
+  if (!page->is_mapped()) {
+    _physical.map(page->physical_memory(), page->start());
+  } else if (ZVerifyViews) {
+    _physical.debug_map(page->physical_memory(), page->start());
   }
-
-  delete page;
 }
 
-void ZPageAllocator::flush_detached_pages(ZList<ZPage>* list) {
-  ZLocker<ZLock> locker(&_lock);
-  list->transfer(&_detached);
+void ZPageAllocator::unmap_all_pages() {
+  ZPhysicalMemory pmem(ZPhysicalMemorySegment(0 /* start */, ZAddressOffsetMax));
+  _physical.debug_unmap(pmem, 0 /* offset */);
+  pmem.clear();
 }
 
 void ZPageAllocator::flush_cache(size_t size) {
@@ -278,7 +272,7 @@
   _cache.flush(&list, size);
 
   for (ZPage* page = list.remove_first(); page != NULL; page = list.remove_first()) {
-    detach_page(page);
+    destroy_page(page);
   }
 }
 
@@ -398,9 +392,7 @@
   }
 
   // Map page if needed
-  if (!page->is_mapped()) {
-    map_page(page);
-  }
+  map_page(page);
 
   // Reset page. This updates the page's sequence number and must
   // be done after page allocation, which potentially blocked in
@@ -445,6 +437,9 @@
 void ZPageAllocator::detach_memory(const ZVirtualMemory& vmem, ZPhysicalMemory& pmem) {
   const uintptr_t addr = vmem.start();
 
+  // Free virtual memory
+  _virtual.free(vmem);
+
   // Unmap physical memory
   _physical.unmap(pmem, addr);
 
@@ -455,27 +450,6 @@
   pmem.clear();
 }
 
-void ZPageAllocator::flip_page(ZPage* page) {
-  const ZPhysicalMemory& pmem = page->physical_memory();
-  const uintptr_t addr = page->start();
-
-  // Flip physical mapping
-  _physical.flip(pmem, addr);
-}
-
-void ZPageAllocator::flip_pre_mapped() {
-  if (_pre_mapped.available() == 0) {
-    // Nothing to flip
-    return;
-  }
-
-  const ZPhysicalMemory& pmem = _pre_mapped.physical_memory();
-  const ZVirtualMemory& vmem = _pre_mapped.virtual_memory();
-
-  // Flip physical mapping
-  _physical.flip(pmem, vmem.start());
-}
-
 void ZPageAllocator::free_page(ZPage* page, bool reclaimed) {
   ZLocker<ZLock> locker(&_lock);
 
@@ -489,6 +463,14 @@
   satisfy_alloc_queue();
 }
 
+void ZPageAllocator::enable_deferred_delete() const {
+  _safe_delete.enable_deferred_delete();
+}
+
+void ZPageAllocator::disable_deferred_delete() const {
+  _safe_delete.disable_deferred_delete();
+}
+
 bool ZPageAllocator::is_alloc_stalled() const {
   assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
   return !_queue.is_empty();
--- a/src/hotspot/share/gc/z/zPageAllocator.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPageAllocator.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
 #include "gc/z/zPageCache.hpp"
 #include "gc/z/zPhysicalMemory.hpp"
 #include "gc/z/zPreMappedMemory.hpp"
+#include "gc/z/zSafeDelete.hpp"
 #include "gc/z/zVirtualMemory.hpp"
 #include "memory/allocation.hpp"
 
@@ -39,19 +40,19 @@
   friend class VMStructs;
 
 private:
-  ZLock                    _lock;
-  ZVirtualMemoryManager    _virtual;
-  ZPhysicalMemoryManager   _physical;
-  ZPageCache               _cache;
-  const size_t             _max_reserve;
-  ZPreMappedMemory         _pre_mapped;
-  size_t                   _used_high;
-  size_t                   _used_low;
-  size_t                   _used;
-  size_t                   _allocated;
-  ssize_t                  _reclaimed;
-  ZList<ZPageAllocRequest> _queue;
-  ZList<ZPage>             _detached;
+  ZLock                      _lock;
+  ZVirtualMemoryManager      _virtual;
+  ZPhysicalMemoryManager     _physical;
+  ZPageCache                 _cache;
+  const size_t               _max_reserve;
+  ZPreMappedMemory           _pre_mapped;
+  size_t                     _used_high;
+  size_t                     _used_low;
+  size_t                     _used;
+  size_t                     _allocated;
+  ssize_t                    _reclaimed;
+  ZList<ZPageAllocRequest>   _queue;
+  mutable ZSafeDelete<ZPage> _safe_delete;
 
   static ZPage* const      gc_marker;
 
@@ -63,8 +64,8 @@
   size_t try_ensure_unused_for_pre_mapped(size_t size);
 
   ZPage* create_page(uint8_t type, size_t size);
-  void map_page(ZPage* page);
-  void detach_page(ZPage* page);
+  void destroy_page(ZPage* page);
+
   void flush_pre_mapped();
   void flush_cache(size_t size);
 
@@ -97,13 +98,13 @@
   void reset_statistics();
 
   ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags);
-  void flip_page(ZPage* page);
   void free_page(ZPage* page, bool reclaimed);
-  void destroy_page(ZPage* page);
 
-  void flush_detached_pages(ZList<ZPage>* list);
+  void enable_deferred_delete() const;
+  void disable_deferred_delete() const;
 
-  void flip_pre_mapped();
+  void map_page(ZPage* page);
+  void unmap_all_pages();
 
   bool is_alloc_stalled() const;
   void check_out_of_memory();
--- a/src/hotspot/share/gc/z/zPageCache.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPageCache.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -118,10 +118,6 @@
 }
 
 void ZPageCache::free_page(ZPage* page) {
-  assert(!page->is_active(), "Invalid page state");
-  assert(!page->is_pinned(), "Invalid page state");
-  assert(!page->is_detached(), "Invalid page state");
-
   const uint8_t type = page->type();
   if (type == ZPageTypeSmall) {
     _small.get(page->numa_id()).insert_first(page);
--- a/src/hotspot/share/gc/z/zPageTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPageTable.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -23,6 +23,7 @@
 
 #include "precompiled.hpp"
 #include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zGranuleMap.inline.hpp"
 #include "gc/z/zPage.inline.hpp"
 #include "gc/z/zPageTable.inline.hpp"
 #include "runtime/orderAccess.hpp"
@@ -31,65 +32,22 @@
 ZPageTable::ZPageTable() :
     _map() {}
 
-ZPageTableEntry ZPageTable::get_entry(ZPage* page) const {
+void ZPageTable::insert(ZPage* page) {
   const uintptr_t addr = ZAddress::good(page->start());
-  return _map.get(addr);
-}
+  const size_t size = page->size();
 
-void ZPageTable::put_entry(ZPage* page, ZPageTableEntry entry) {
-  // Make sure a newly created page is globally visible before
-  // updating the pagetable.
+  // Make sure a newly created page is
+  // visible before updating the page table.
   OrderAccess::storestore();
 
-  const uintptr_t start = ZAddress::good(page->start());
-  const uintptr_t end = start + page->size();
-  for (uintptr_t addr = start; addr < end; addr += ZGranuleSize) {
-    _map.put(addr, entry);
-  }
-}
-
-void ZPageTable::insert(ZPage* page) {
-  assert(get_entry(page).page() == NULL ||
-         get_entry(page).page() == page, "Invalid entry");
-
-  // Cached pages stays in the pagetable and we must not re-insert
-  // those when they get re-allocated because they might also be
-  // relocating and we don't want to clear their relocating bit.
-  if (get_entry(page).page() == NULL) {
-    ZPageTableEntry entry(page, false /* relocating */);
-    put_entry(page, entry);
-  }
-
-  assert(get_entry(page).page() == page, "Invalid entry");
+  assert(get(addr) == NULL, "Invalid entry");
+  _map.put(addr, size, page);
 }
 
 void ZPageTable::remove(ZPage* page) {
-  assert(get_entry(page).page() == page, "Invalid entry");
-
-  ZPageTableEntry entry;
-  put_entry(page, entry);
-
-  assert(get_entry(page).page() == NULL, "Invalid entry");
-}
-
-void ZPageTable::set_relocating(ZPage* page) {
-  assert(get_entry(page).page() == page, "Invalid entry");
-  assert(!get_entry(page).relocating(), "Invalid entry");
-
-  ZPageTableEntry entry(page, true /* relocating */);
-  put_entry(page, entry);
+  const uintptr_t addr = ZAddress::good(page->start());
+  const size_t size = page->size();
 
-  assert(get_entry(page).page() == page, "Invalid entry");
-  assert(get_entry(page).relocating(), "Invalid entry");
+  assert(get(addr) == page, "Invalid entry");
+  _map.put(addr, size, NULL);
 }
-
-void ZPageTable::clear_relocating(ZPage* page) {
-  assert(get_entry(page).page() == page, "Invalid entry");
-  assert(get_entry(page).relocating(), "Invalid entry");
-
-  ZPageTableEntry entry(page, false /* relocating */);
-  put_entry(page, entry);
-
-  assert(get_entry(page).page() == page, "Invalid entry");
-  assert(!get_entry(page).relocating(), "Invalid entry");
-}
--- a/src/hotspot/share/gc/z/zPageTable.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPageTable.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -25,7 +25,6 @@
 #define SHARE_GC_Z_ZPAGETABLE_HPP
 
 #include "gc/z/zGranuleMap.hpp"
-#include "gc/z/zPageTableEntry.hpp"
 #include "memory/allocation.hpp"
 
 class ZPage;
@@ -35,30 +34,24 @@
   friend class ZPageTableIterator;
 
 private:
-  ZGranuleMap<ZPageTableEntry> _map;
-
-  ZPageTableEntry get_entry(ZPage* page) const;
-  void put_entry(ZPage* page, ZPageTableEntry entry);
+  ZGranuleMap<ZPage*> _map;
 
 public:
   ZPageTable();
 
   ZPage* get(uintptr_t addr) const;
+
   void insert(ZPage* page);
   void remove(ZPage* page);
-
-  bool is_relocating(uintptr_t addr) const;
-  void set_relocating(ZPage* page);
-  void clear_relocating(ZPage* page);
 };
 
 class ZPageTableIterator : public StackObj {
 private:
-  ZGranuleMapIterator<ZPageTableEntry> _iter;
-  ZPage*                               _prev;
+  ZGranuleMapIterator<ZPage*> _iter;
+  ZPage*                      _prev;
 
 public:
-  ZPageTableIterator(const ZPageTable* pagetable);
+  ZPageTableIterator(const ZPageTable* page_table);
 
   bool next(ZPage** page);
 };
--- a/src/hotspot/share/gc/z/zPageTable.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPageTable.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -29,25 +29,18 @@
 #include "gc/z/zPageTable.hpp"
 
 inline ZPage* ZPageTable::get(uintptr_t addr) const {
-  return _map.get(addr).page();
+  return _map.get(addr);
 }
 
-inline bool ZPageTable::is_relocating(uintptr_t addr) const {
-  return _map.get(addr).relocating();
-}
-
-inline ZPageTableIterator::ZPageTableIterator(const ZPageTable* pagetable) :
-    _iter(&pagetable->_map),
+inline ZPageTableIterator::ZPageTableIterator(const ZPageTable* page_table) :
+    _iter(&page_table->_map),
     _prev(NULL) {}
 
 inline bool ZPageTableIterator::next(ZPage** page) {
-  ZPageTableEntry entry;
-
-  while (_iter.next(&entry)) {
-    ZPage* const next = entry.page();
-    if (next != NULL && next != _prev) {
+  for (ZPage* entry; _iter.next(&entry);) {
+    if (entry != NULL && entry != _prev) {
       // Next page found
-      *page = _prev = next;
+      *page = _prev = entry;
       return true;
     }
   }
--- a/src/hotspot/share/gc/z/zPageTableEntry.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * 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_ZPAGETABLEENTRY_HPP
-#define SHARE_GC_Z_ZPAGETABLEENTRY_HPP
-
-#include "gc/z/zBitField.hpp"
-#include "memory/allocation.hpp"
-
-//
-// Page table entry layout
-// -----------------------
-//
-//   6
-//   3                                                                    1 0
-//  +----------------------------------------------------------------------+-+
-//  |11111111 11111111 11111111 11111111 11111111 11111111 11111111 1111111|1|
-//  +----------------------------------------------------------------------+-+
-//  |                                                                      |
-//  |                                          0-0 Relocating Flag (1-bit) *
-//  |
-//  |
-//  |
-//  * 63-1 Page address (63-bits)
-//
-
-class ZPage;
-
-class ZPageTableEntry {
-private:
-  typedef ZBitField<uint64_t, bool,   0, 1>     field_relocating;
-  typedef ZBitField<uint64_t, ZPage*, 1, 63, 1> field_page;
-
-  uint64_t _entry;
-
-public:
-  ZPageTableEntry() :
-      _entry(0) {}
-
-  ZPageTableEntry(ZPage* page, bool relocating) :
-      _entry(field_page::encode(page) |
-             field_relocating::encode(relocating)) {}
-
-  bool relocating() const {
-    return field_relocating::decode(_entry);
-  }
-
-  ZPage* page() const {
-    return field_page::decode(_entry);
-  }
-};
-
-#endif // SHARE_GC_Z_ZPAGETABLEENTRY_HPP
--- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPhysicalMemory.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -179,6 +179,10 @@
   _backing.unmap(pmem, offset);
 }
 
-void ZPhysicalMemoryManager::flip(ZPhysicalMemory pmem, uintptr_t offset) {
-  _backing.flip(pmem, offset);
+void ZPhysicalMemoryManager::debug_map(ZPhysicalMemory pmem, uintptr_t offset) {
+  _backing.debug_map(pmem, offset);
 }
+
+void ZPhysicalMemoryManager::debug_unmap(ZPhysicalMemory pmem, uintptr_t offset) {
+  _backing.debug_unmap(pmem, offset);
+}
--- a/src/hotspot/share/gc/z/zPhysicalMemory.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zPhysicalMemory.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -94,7 +94,9 @@
 
   void map(ZPhysicalMemory pmem, uintptr_t offset);
   void unmap(ZPhysicalMemory pmem, uintptr_t offset);
-  void flip(ZPhysicalMemory pmem, uintptr_t offset);
+
+  void debug_map(ZPhysicalMemory pmem, uintptr_t offset);
+  void debug_unmap(ZPhysicalMemory pmem, uintptr_t offset);
 };
 
 #endif // SHARE_GC_Z_ZPHYSICALMEMORY_HPP
--- a/src/hotspot/share/gc/z/zRelocate.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zRelocate.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -24,15 +24,20 @@
 #include "precompiled.hpp"
 #include "gc/z/zAddress.inline.hpp"
 #include "gc/z/zBarrier.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
 #include "gc/z/zHeap.hpp"
 #include "gc/z/zOopClosures.inline.hpp"
 #include "gc/z/zPage.hpp"
 #include "gc/z/zRelocate.hpp"
 #include "gc/z/zRelocationSet.inline.hpp"
 #include "gc/z/zRootsIterator.hpp"
+#include "gc/z/zStat.hpp"
 #include "gc/z/zTask.hpp"
 #include "gc/z/zThreadLocalAllocBuffer.hpp"
 #include "gc/z/zWorkers.hpp"
+#include "logging/log.hpp"
+
+static const ZStatCounter ZCounterRelocationContention("Contention", "Relocation Contention", ZStatUnitOpsPerSecond);
 
 ZRelocate::ZRelocate(ZWorkers* workers) :
     _workers(workers) {}
@@ -78,16 +83,89 @@
   _workers->run_parallel(&task);
 }
 
+uintptr_t ZRelocate::relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const {
+  ZForwardingCursor cursor;
+
+  // Lookup forwarding entry
+  const ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+  if (entry.from_index() == from_index) {
+    // Already relocated, return new address
+    return entry.to_offset();
+  }
+
+  assert(ZHeap::heap()->is_object_live(ZAddress::good(from_offset)), "Should be live");
+
+  if (forwarding->is_pinned()) {
+    // In-place forward
+    return forwarding->insert(from_index, from_offset, &cursor);
+  }
+
+  // Allocate object
+  const uintptr_t from_good = ZAddress::good(from_offset);
+  const size_t size = ZUtils::object_size(from_good);
+  const uintptr_t to_good = ZHeap::heap()->alloc_object_for_relocation(size);
+  if (to_good == 0) {
+    // Failed, in-place forward
+    return forwarding->insert(from_index, from_offset, &cursor);
+  }
+
+  // Copy object
+  ZUtils::object_copy(from_good, to_good, size);
+
+  // Insert forwarding entry
+  const uintptr_t to_offset = ZAddress::offset(to_good);
+  const uintptr_t to_offset_final = forwarding->insert(from_index, to_offset, &cursor);
+  if (to_offset_final == to_offset) {
+    // Relocation succeeded
+    return to_offset;
+  }
+
+  // Relocation contention
+  ZStatInc(ZCounterRelocationContention);
+  log_trace(gc)("Relocation contention, thread: " PTR_FORMAT " (%s), forwarding: " PTR_FORMAT
+                ", entry: " UINT32_FORMAT ", oop: " PTR_FORMAT ", size: " SIZE_FORMAT,
+                ZThread::id(), ZThread::name(), p2i(forwarding), cursor, from_good, size);
+
+  // Try undo allocation
+  ZHeap::heap()->undo_alloc_object_for_relocation(to_good, size);
+
+  return to_offset_final;
+}
+
+uintptr_t ZRelocate::relocate_object(ZForwarding* forwarding, uintptr_t from_addr) const {
+  const uintptr_t from_offset = ZAddress::offset(from_addr);
+  const uintptr_t from_index = (from_offset - forwarding->start()) >> forwarding->object_alignment_shift();
+  const uintptr_t to_offset = relocate_object_inner(forwarding, from_index, from_offset);
+
+  if (from_offset == to_offset) {
+    // In-place forwarding, pin page
+    forwarding->set_pinned();
+  }
+
+  return ZAddress::good(to_offset);
+}
+
+uintptr_t ZRelocate::forward_object(ZForwarding* forwarding, uintptr_t from_addr) const {
+  const uintptr_t from_offset = ZAddress::offset(from_addr);
+  const uintptr_t from_index = (from_offset - forwarding->start()) >> forwarding->object_alignment_shift();
+  const ZForwardingEntry entry = forwarding->find(from_index);
+
+  assert(entry.from_index() == from_index, "Should be forwarded");
+  return ZAddress::good(entry.to_offset());
+}
+
 class ZRelocateObjectClosure : public ObjectClosure {
 private:
-  ZPage* const _page;
+  ZRelocate* const   _relocate;
+  ZForwarding* const _forwarding;
 
 public:
-  ZRelocateObjectClosure(ZPage* page) :
-      _page(page) {}
+  ZRelocateObjectClosure(ZRelocate* relocate, ZForwarding* forwarding) :
+      _relocate(relocate),
+      _forwarding(forwarding) {}
 
   virtual void do_object(oop o) {
-    _page->relocate_object(ZOop::to_address(o));
+    _relocate->relocate_object(_forwarding, ZOop::to_address(o));
   }
 };
 
@@ -95,21 +173,21 @@
   bool success = true;
 
   // Relocate pages in the relocation set
-  for (ZPage* page; iter->next(&page);) {
+  for (ZForwarding* forwarding; iter->next(&forwarding);) {
     // Relocate objects in page
-    ZRelocateObjectClosure cl(page);
-    page->object_iterate(&cl);
+    ZRelocateObjectClosure cl(this, forwarding);
+    forwarding->page()->object_iterate(&cl);
 
     if (ZVerifyForwarding) {
-      page->verify_forwarding();
+      forwarding->verify();
     }
 
-    if (page->is_pinned()) {
+    if (forwarding->is_pinned()) {
       // Relocation failed, page is now pinned
       success = false;
     } else {
       // Relocation succeeded, release page
-      ZHeap::heap()->release_page(page, true /* reclaimed */);
+      forwarding->release_page();
     }
   }
 
--- a/src/hotspot/share/gc/z/zRelocate.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zRelocate.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,17 +28,24 @@
 #include "gc/z/zWorkers.hpp"
 #include "memory/allocation.hpp"
 
+class ZForwarding;
+
 class ZRelocate {
   friend class ZRelocateTask;
 
 private:
   ZWorkers* const _workers;
 
+  ZForwarding* forwarding_for_page(ZPage* page) const;
+  uintptr_t relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const;
   bool work(ZRelocationSetParallelIterator* iter);
 
 public:
   ZRelocate(ZWorkers* workers);
 
+  uintptr_t relocate_object(ZForwarding* forwarding, uintptr_t from_addr) const;
+  uintptr_t forward_object(ZForwarding* forwarding, uintptr_t from_addr) const;
+
   void start();
   bool relocate(ZRelocationSet* relocation_set);
 };
--- a/src/hotspot/share/gc/z/zRelocationSet.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zRelocationSet.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,24 +22,35 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/z/zForwarding.hpp"
 #include "gc/z/zRelocationSet.hpp"
-#include "memory/allocation.inline.hpp"
+#include "memory/allocation.hpp"
 
 ZRelocationSet::ZRelocationSet() :
-    _pages(NULL),
-    _npages(0) {}
+    _forwardings(NULL),
+    _nforwardings(0) {}
 
-void ZRelocationSet::populate(const ZPage* const* group0, size_t ngroup0,
-                              const ZPage* const* group1, size_t ngroup1) {
-  _npages = ngroup0 + ngroup1;
-  _pages = REALLOC_C_HEAP_ARRAY(ZPage*, _pages, _npages, mtGC);
+void ZRelocationSet::populate(ZPage* const* group0, size_t ngroup0,
+                              ZPage* const* group1, size_t ngroup1) {
+  _nforwardings = ngroup0 + ngroup1;
+  _forwardings = REALLOC_C_HEAP_ARRAY(ZForwarding*, _forwardings, _nforwardings, mtGC);
 
-  if (_pages != NULL) {
-    if (group0 != NULL) {
-      memcpy(_pages, group0, ngroup0 * sizeof(ZPage*));
-    }
-    if (group1 != NULL) {
-      memcpy(_pages + ngroup0, group1, ngroup1 * sizeof(ZPage*));
-    }
+  size_t j = 0;
+
+  // Populate group 0
+  for (size_t i = 0; i < ngroup0; i++) {
+    _forwardings[j++] = ZForwarding::create(group0[i]);
+  }
+
+  // Populate group 1
+  for (size_t i = 0; i < ngroup1; i++) {
+    _forwardings[j++] = ZForwarding::create(group1[i]);
   }
 }
+
+void ZRelocationSet::reset() {
+  for (size_t i = 0; i < _nforwardings; i++) {
+    ZForwarding::destroy(_forwardings[i]);
+    _forwardings[i] = NULL;
+  }
+}
--- a/src/hotspot/share/gc/z/zRelocationSet.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zRelocationSet.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,20 +26,22 @@
 
 #include "memory/allocation.hpp"
 
+class ZForwarding;
 class ZPage;
 
 class ZRelocationSet {
   template <bool> friend class ZRelocationSetIteratorImpl;
 
 private:
-  ZPage** _pages;
-  size_t  _npages;
+  ZForwarding** _forwardings;
+  size_t        _nforwardings;
 
 public:
   ZRelocationSet();
 
-  void populate(const ZPage* const* group0, size_t ngroup0,
-                const ZPage* const* group1, size_t ngroup1);
+  void populate(ZPage* const* group0, size_t ngroup0,
+                ZPage* const* group1, size_t ngroup1);
+  void reset();
 };
 
 template <bool parallel>
@@ -51,7 +53,7 @@
 public:
   ZRelocationSetIteratorImpl(ZRelocationSet* relocation_set);
 
-  bool next(ZPage** page);
+  bool next(ZForwarding** forwarding);
 };
 
 // Iterator types
--- a/src/hotspot/share/gc/z/zRelocationSet.inline.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zRelocationSet.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,20 +33,20 @@
     _next(0) {}
 
 template <bool parallel>
-inline bool ZRelocationSetIteratorImpl<parallel>::next(ZPage** page) {
-  const size_t npages = _relocation_set->_npages;
+inline bool ZRelocationSetIteratorImpl<parallel>::next(ZForwarding** forwarding) {
+  const size_t nforwardings = _relocation_set->_nforwardings;
 
   if (parallel) {
-    if (_next < npages) {
+    if (_next < nforwardings) {
       const size_t next = Atomic::add(1u, &_next) - 1u;
-      if (next < npages) {
-        *page = _relocation_set->_pages[next];
+      if (next < nforwardings) {
+        *forwarding = _relocation_set->_forwardings[next];
         return true;
       }
     }
   } else {
-    if (_next < npages) {
-      *page = _relocation_set->_pages[_next++];
+    if (_next < nforwardings) {
+      *forwarding = _relocation_set->_forwardings[_next++];
       return true;
     }
   }
--- a/src/hotspot/share/gc/z/zRelocationSetSelector.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zRelocationSetSelector.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,10 +44,10 @@
     _fragmentation(0) {}
 
 ZRelocationSetSelectorGroup::~ZRelocationSetSelectorGroup() {
-  FREE_C_HEAP_ARRAY(const ZPage*, _sorted_pages);
+  FREE_C_HEAP_ARRAY(ZPage*, _sorted_pages);
 }
 
-void ZRelocationSetSelectorGroup::register_live_page(const ZPage* page, size_t garbage) {
+void ZRelocationSetSelectorGroup::register_live_page(ZPage* page, size_t garbage) {
   if (garbage > _fragmentation_limit) {
     _registered_pages.add(page);
   } else {
@@ -67,13 +67,13 @@
   size_t partitions[npartitions];
 
   // Allocate destination array
-  _sorted_pages = REALLOC_C_HEAP_ARRAY(const ZPage*, _sorted_pages, npages, mtGC);
+  _sorted_pages = REALLOC_C_HEAP_ARRAY(ZPage*, _sorted_pages, npages, mtGC);
   debug_only(memset(_sorted_pages, 0, npages * sizeof(ZPage*)));
 
   // Calculate partition slots
   memset(partitions, 0, sizeof(partitions));
-  ZArrayIterator<const ZPage*> iter1(&_registered_pages);
-  for (const ZPage* page; iter1.next(&page);) {
+  ZArrayIterator<ZPage*> iter1(&_registered_pages);
+  for (ZPage* page; iter1.next(&page);) {
     const size_t index = page->live_bytes() >> partition_size_shift;
     partitions[index]++;
   }
@@ -87,8 +87,8 @@
   }
 
   // Sort pages into partitions
-  ZArrayIterator<const ZPage*> iter2(&_registered_pages);
-  for (const ZPage* page; iter2.next(&page);) {
+  ZArrayIterator<ZPage*> iter2(&_registered_pages);
+  for (ZPage* page; iter2.next(&page);) {
     const size_t index = page->live_bytes() >> partition_size_shift;
     const size_t finger = partitions[index]++;
     assert(_sorted_pages[finger] == NULL, "Invalid finger");
@@ -140,7 +140,7 @@
   // Update statistics
   _relocating = from_size;
   for (size_t i = _nselected; i < npages; i++) {
-    const ZPage* const page = _sorted_pages[i];
+    ZPage* const page = _sorted_pages[i];
     _fragmentation += page->size() - page->live_bytes();
   }
 
@@ -148,7 +148,7 @@
                        _name, selected_from, selected_to, npages - _nselected);
 }
 
-const ZPage* const* ZRelocationSetSelectorGroup::selected() const {
+ZPage* const* ZRelocationSetSelectorGroup::selected() const {
   return _sorted_pages;
 }
 
@@ -171,7 +171,7 @@
     _garbage(0),
     _fragmentation(0) {}
 
-void ZRelocationSetSelector::register_live_page(const ZPage* page) {
+void ZRelocationSetSelector::register_live_page(ZPage* page) {
   const uint8_t type = page->type();
   const size_t live = page->live_bytes();
   const size_t garbage = page->size() - live;
@@ -188,7 +188,7 @@
   _garbage += garbage;
 }
 
-void ZRelocationSetSelector::register_garbage_page(const ZPage* page) {
+void ZRelocationSetSelector::register_garbage_page(ZPage* page) {
   _garbage += page->size();
 }
 
--- a/src/hotspot/share/gc/z/zRelocationSetSelector.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zRelocationSetSelector.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,16 +32,16 @@
 
 class ZRelocationSetSelectorGroup {
 private:
-  const char* const    _name;
-  const size_t         _page_size;
-  const size_t         _object_size_limit;
-  const size_t         _fragmentation_limit;
+  const char* const _name;
+  const size_t      _page_size;
+  const size_t      _object_size_limit;
+  const size_t      _fragmentation_limit;
 
-  ZArray<const ZPage*> _registered_pages;
-  const ZPage**        _sorted_pages;
-  size_t               _nselected;
-  size_t               _relocating;
-  size_t               _fragmentation;
+  ZArray<ZPage*>    _registered_pages;
+  ZPage**           _sorted_pages;
+  size_t            _nselected;
+  size_t            _relocating;
+  size_t            _fragmentation;
 
   void semi_sort();
 
@@ -51,10 +51,10 @@
                               size_t object_size_limit);
   ~ZRelocationSetSelectorGroup();
 
-  void register_live_page(const ZPage* page, size_t garbage);
+  void register_live_page(ZPage* page, size_t garbage);
   void select();
 
-  const ZPage* const* selected() const;
+  ZPage* const* selected() const;
   size_t nselected() const;
   size_t relocating() const;
   size_t fragmentation() const;
@@ -71,8 +71,8 @@
 public:
   ZRelocationSetSelector();
 
-  void register_live_page(const ZPage* page);
-  void register_garbage_page(const ZPage* page);
+  void register_live_page(ZPage* page);
+  void register_garbage_page(ZPage* page);
   void select(ZRelocationSet* relocation_set);
 
   size_t live() const;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zSafeDelete.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZSAFEDELETE_HPP
+#define SHARE_GC_Z_ZSAFEDELETE_HPP
+
+#include "gc/z/zArray.hpp"
+#include "gc/z/zLock.hpp"
+#include "metaprogramming/removeExtent.hpp"
+
+template <typename T>
+class ZSafeDelete {
+private:
+  typedef typename RemoveExtent<T>::type ItemT;
+
+  ZLock          _lock;
+  uint64_t       _enabled;
+  ZArray<ItemT*> _deferred;
+
+  bool deferred_delete(ItemT* item);
+  void immediate_delete(ItemT* item);
+
+public:
+  ZSafeDelete();
+
+  void enable_deferred_delete();
+  void disable_deferred_delete();
+
+  void operator()(ItemT* item);
+};
+
+#endif // SHARE_GC_Z_ZSAFEDELETE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zSafeDelete.inline.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZSAFEDELETE_INLINE_HPP
+#define SHARE_GC_Z_ZSAFEDELETE_INLINE_HPP
+
+#include "gc/z/zArray.inline.hpp"
+#include "gc/z/zSafeDelete.hpp"
+#include "metaprogramming/isArray.hpp"
+#include "utilities/debug.hpp"
+
+template <typename T>
+ZSafeDelete<T>::ZSafeDelete() :
+    _lock(),
+    _enabled(0),
+    _deferred() {}
+
+template <typename T>
+bool ZSafeDelete<T>::deferred_delete(ItemT* item) {
+  ZLocker<ZLock> locker(&_lock);
+  if (_enabled > 0) {
+    _deferred.add(item);
+    return true;
+  }
+
+  return false;
+}
+
+template <typename T>
+void ZSafeDelete<T>::immediate_delete(ItemT* item) {
+  if (IsArray<T>::value) {
+    delete [] item;
+  } else {
+    delete item;
+  }
+}
+
+template <typename T>
+void ZSafeDelete<T>::enable_deferred_delete() {
+  ZLocker<ZLock> locker(&_lock);
+  _enabled++;
+}
+
+template <typename T>
+void ZSafeDelete<T>::disable_deferred_delete() {
+  ZArray<ItemT*> deferred;
+
+  {
+    ZLocker<ZLock> locker(&_lock);
+    assert(_enabled > 0, "Invalid state");
+    if (--_enabled == 0) {
+      deferred.transfer(&_deferred);
+    }
+  }
+
+  ZArrayIterator<ItemT*> iter(&deferred);
+  for (ItemT* item; iter.next(&item);) {
+    immediate_delete(item);
+  }
+}
+
+template <typename T>
+void ZSafeDelete<T>::operator()(ItemT* item) {
+  if (!deferred_delete(item)) {
+    immediate_delete(item);
+  }
+}
+
+#endif // SHARE_GC_Z_ZSAFEDELETE_INLINE_HPP
--- a/src/hotspot/share/gc/z/z_globals.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/gc/z/z_globals.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,28 +39,24 @@
                    constraint,                                              \
                    writeable)                                               \
                                                                             \
-  product(ccstr, ZPath, NULL,                                               \
+  experimental(ccstr, ZPath, NULL,                                          \
           "Filesystem path for Java heap backing storage "                  \
           "(must be a tmpfs or a hugetlbfs filesystem)")                    \
                                                                             \
-  product(double, ZAllocationSpikeTolerance, 2.0,                           \
+  experimental(double, ZAllocationSpikeTolerance, 2.0,                      \
           "Allocation spike tolerance factor")                              \
                                                                             \
-  product(double, ZFragmentationLimit, 25.0,                                \
+  experimental(double, ZFragmentationLimit, 25.0,                           \
           "Maximum allowed heap fragmentation")                             \
                                                                             \
-  product(bool, ZStallOnOutOfMemory, true,                                  \
-          "Allow Java threads to stall and wait for GC to complete "        \
-          "instead of immediately throwing an OutOfMemoryError")            \
-                                                                            \
-  product(size_t, ZMarkStackSpaceLimit, 8*G,                                \
+  experimental(size_t, ZMarkStackSpaceLimit, 8*G,                           \
           "Maximum number of bytes allocated for mark stacks")              \
           range(32*M, 1024*G)                                               \
                                                                             \
-  product(uint, ZCollectionInterval, 0,                                     \
+  experimental(uint, ZCollectionInterval, 0,                                \
           "Force GC at a fixed time interval (in seconds)")                 \
                                                                             \
-  product(uint, ZStatisticsInterval, 10,                                    \
+  diagnostic(uint, ZStatisticsInterval, 10,                                 \
           "Time between statistics print outs (in seconds)")                \
           range(1, (uint)-1)                                                \
                                                                             \
@@ -70,8 +66,8 @@
   diagnostic(bool, ZProactive, true,                                        \
           "Enable proactive GC cycles")                                     \
                                                                             \
-  diagnostic(bool, ZUnmapBadViews, false,                                   \
-          "Unmap bad (inactive) heap views")                                \
+  diagnostic(bool, ZVerifyViews, false,                                     \
+          "Verify heap view accesses")                                      \
                                                                             \
   diagnostic(bool, ZVerifyMarking, false,                                   \
           "Verify marking stacks")                                          \
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunkWriter.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,13 +46,9 @@
   return _chunkstate != NULL;
 }
 
-static fio_fd open_existing(const char* path) {
-  return os::open(path, O_RDWR, S_IREAD | S_IWRITE);
-}
-
 static fio_fd open_chunk(const char* path) {
   assert(JfrStream_lock->owned_by_self(), "invariant");
-  return path != NULL ? open_existing(path) : invalid_fd;
+  return path != NULL ? os::open(path, O_CREAT | O_RDWR, S_IREAD | S_IWRITE) : invalid_fd;
 }
 
 bool JfrChunkWriter::open() {
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -24,17 +24,315 @@
 
 #include "precompiled.hpp"
 #include "jfr/jfrEvents.hpp"
+#include "jfr/jni/jfrJavaSupport.hpp"
 #include "jfr/leakprofiler/leakProfiler.hpp"
 #include "jfr/recorder/repository/jfrEmergencyDump.hpp"
 #include "jfr/recorder/service/jfrPostBox.hpp"
 #include "jfr/recorder/service/jfrRecorderService.hpp"
 #include "jfr/utilities/jfrTypes.hpp"
+#include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/os.hpp"
+#include "runtime/thread.inline.hpp"
+#include "utilities/growableArray.hpp"
+
+static const char vm_error_filename_fmt[] = "hs_err_pid%p.jfr";
+static const char vm_oom_filename_fmt[] = "hs_oom_pid%p.jfr";
+static const char vm_soe_filename_fmt[] = "hs_soe_pid%p.jfr";
+static const char chunk_file_jfr_ext[] = ".jfr";
+static const size_t iso8601_len = 19; // "YYYY-MM-DDTHH:MM:SS"
+
+static fio_fd open_exclusivly(const char* path) {
+  return os::open(path, O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
+}
+
+static int file_sort(const char** const file1, const char** file2) {
+  assert(NULL != *file1 && NULL != *file2, "invariant");
+  int cmp = strncmp(*file1, *file2, iso8601_len);
+  if (0 == cmp) {
+    const char* const dot1 = strchr(*file1, '.');
+    assert(NULL != dot1, "invariant");
+    const char* const dot2 = strchr(*file2, '.');
+    assert(NULL != dot2, "invariant");
+    ptrdiff_t file1_len = dot1 - *file1;
+    ptrdiff_t file2_len = dot2 - *file2;
+    if (file1_len < file2_len) {
+      return -1;
+    }
+    if (file1_len > file2_len) {
+      return 1;
+    }
+    assert(file1_len == file2_len, "invariant");
+    cmp = strncmp(*file1, *file2, file1_len);
+  }
+  assert(cmp != 0, "invariant");
+  return cmp;
+}
+
+static void iso8601_to_date_time(char* iso8601_str) {
+  assert(iso8601_str != NULL, "invariant");
+  assert(strlen(iso8601_str) == iso8601_len, "invariant");
+  // "YYYY-MM-DDTHH:MM:SS"
+  for (size_t i = 0; i < iso8601_len; ++i) {
+    switch (iso8601_str[i]) {
+    case 'T':
+    case '-':
+    case ':':
+      iso8601_str[i] = '_';
+      break;
+    }
+  }
+  // "YYYY_MM_DD_HH_MM_SS"
+}
+
+static void date_time(char* buffer, size_t buffer_len) {
+  assert(buffer != NULL, "invariant");
+  assert(buffer_len >= iso8601_len, "buffer too small");
+  os::iso8601_time(buffer, buffer_len);
+  assert(strlen(buffer) >= iso8601_len + 1, "invariant");
+  // "YYYY-MM-DDTHH:MM:SS"
+  buffer[iso8601_len] = '\0';
+  iso8601_to_date_time(buffer);
+}
+
+static int64_t file_size(fio_fd fd) {
+  assert(fd != invalid_fd, "invariant");
+  const int64_t current_offset = os::current_file_offset(fd);
+  const int64_t size = os::lseek(fd, 0, SEEK_END);
+  os::seek_to_file_offset(fd, current_offset);
+  return size;
+}
+
+class RepositoryIterator : public StackObj {
+ private:
+  const char* const _repo;
+  const size_t _repository_len;
+  GrowableArray<const char*>* _files;
+  const char* const fully_qualified(const char* entry) const;
+  mutable int _iterator;
+
+ public:
+  RepositoryIterator(const char* repository, size_t repository_len);
+  ~RepositoryIterator() {}
+  const char* const filter(const char* entry) const;
+  bool has_next() const;
+  const char* const next() const;
+};
+
+const char* const RepositoryIterator::fully_qualified(const char* entry) const {
+  assert(NULL != entry, "invariant");
+  char* file_path_entry = NULL;
+  // only use files that have content, not placeholders
+  const char* const file_separator = os::file_separator();
+  if (NULL != file_separator) {
+    const size_t entry_len = strlen(entry);
+    const size_t file_separator_length = strlen(file_separator);
+    const size_t file_path_entry_length = _repository_len + file_separator_length + entry_len;
+    file_path_entry = NEW_RESOURCE_ARRAY_RETURN_NULL(char, file_path_entry_length + 1);
+    if (NULL == file_path_entry) {
+      return NULL;
+    }
+    int position = 0;
+    position += jio_snprintf(&file_path_entry[position], _repository_len + 1, "%s", _repo);
+    position += jio_snprintf(&file_path_entry[position], file_separator_length + 1, "%s", os::file_separator());
+    position += jio_snprintf(&file_path_entry[position], entry_len + 1, "%s", entry);
+    file_path_entry[position] = '\0';
+    assert((size_t)position == file_path_entry_length, "invariant");
+    assert(strlen(file_path_entry) == (size_t)position, "invariant");
+  }
+  return file_path_entry;
+}
+
+const char* const RepositoryIterator::filter(const char* entry) const {
+  if (entry == NULL) {
+    return NULL;
+  }
+  const size_t entry_len = strlen(entry);
+  if (entry_len <= 2) {
+    // for "." and ".."
+    return NULL;
+  }
+  char* entry_name = NEW_RESOURCE_ARRAY_RETURN_NULL(char, entry_len + 1);
+  if (entry_name == NULL) {
+    return NULL;
+  }
+  strncpy(entry_name, entry, entry_len + 1);
+  const char* const fully_qualified_path_entry = fully_qualified(entry_name);
+  if (NULL == fully_qualified_path_entry) {
+    return NULL;
+  }
+  const fio_fd entry_fd = open_exclusivly(fully_qualified_path_entry);
+  if (invalid_fd == entry_fd) {
+    return NULL;
+  }
+  const int64_t entry_size = file_size(entry_fd);
+  os::close(entry_fd);
+  if (0 == entry_size) {
+    return NULL;
+  }
+  return entry_name;
+}
+
+RepositoryIterator::RepositoryIterator(const char* repository, size_t repository_len) :
+  _repo(repository),
+  _repository_len(repository_len),
+  _files(NULL),
+  _iterator(0) {
+  if (NULL != _repo) {
+    assert(strlen(_repo) == _repository_len, "invariant");
+    _files = new GrowableArray<const char*>(10);
+    DIR* dirp = os::opendir(_repo);
+    if (dirp == NULL) {
+      log_error(jfr, system)("Unable to open repository %s", _repo);
+      return;
+    }
+    struct dirent* dentry;
+    while ((dentry = os::readdir(dirp)) != NULL) {
+      const char* const entry_path = filter(dentry->d_name);
+      if (NULL != entry_path) {
+        _files->append(entry_path);
+      }
+    }
+    os::closedir(dirp);
+    if (_files->length() > 1) {
+      _files->sort(file_sort);
+    }
+  }
+}
+
+bool RepositoryIterator::has_next() const {
+  return (_files != NULL && _iterator < _files->length());
+}
+
+const char* const RepositoryIterator::next() const {
+  return _iterator >= _files->length() ? NULL : fully_qualified(_files->at(_iterator++));
+}
+
+static void write_emergency_file(fio_fd emergency_fd, const RepositoryIterator& iterator) {
+  assert(emergency_fd != invalid_fd, "invariant");
+  const size_t size_of_file_copy_block = 1 * M; // 1 mb
+  jbyte* const file_copy_block = NEW_RESOURCE_ARRAY_RETURN_NULL(jbyte, size_of_file_copy_block);
+  if (file_copy_block == NULL) {
+    return;
+  }
+  while (iterator.has_next()) {
+    fio_fd current_fd = invalid_fd;
+    const char* const fqn = iterator.next();
+    if (fqn != NULL) {
+      current_fd = open_exclusivly(fqn);
+      if (current_fd != invalid_fd) {
+        const int64_t current_filesize = file_size(current_fd);
+        assert(current_filesize > 0, "invariant");
+        int64_t bytes_read = 0;
+        int64_t bytes_written = 0;
+        while (bytes_read < current_filesize) {
+          const ssize_t read_result = os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
+          if (-1 == read_result) {
+            log_info(jfr)( // For user, should not be "jfr, system"
+              "Unable to recover JFR data");
+            break;
+          }
+          bytes_read += (int64_t)read_result;
+          assert(bytes_read - bytes_written <= (int64_t)size_of_file_copy_block, "invariant");
+          bytes_written += (int64_t)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
+          assert(bytes_read == bytes_written, "invariant");
+        }
+        os::close(current_fd);
+      }
+    }
+  }
+}
+
+static const char* create_emergency_dump_path() {
+  assert(JfrStream_lock->owned_by_self(), "invariant");
+  char* buffer = NEW_RESOURCE_ARRAY_RETURN_NULL(char, JVM_MAXPATHLEN);
+  if (NULL == buffer) {
+    return NULL;
+  }
+  const char* const cwd = os::get_current_directory(buffer, JVM_MAXPATHLEN);
+  if (NULL == cwd) {
+    return NULL;
+  }
+  size_t pos = strlen(cwd);
+  const int fsep_len = jio_snprintf(&buffer[pos], JVM_MAXPATHLEN - pos, "%s", os::file_separator());
+  const char* filename_fmt = NULL;
+  // fetch specific error cause
+  switch (JfrJavaSupport::cause()) {
+    case JfrJavaSupport::OUT_OF_MEMORY:
+      filename_fmt = vm_oom_filename_fmt;
+      break;
+    case JfrJavaSupport::STACK_OVERFLOW:
+      filename_fmt = vm_soe_filename_fmt;
+      break;
+    default:
+      filename_fmt = vm_error_filename_fmt;
+  }
+  char* emergency_dump_path = NULL;
+  pos += fsep_len;
+  if (Arguments::copy_expand_pid(filename_fmt, strlen(filename_fmt), &buffer[pos], JVM_MAXPATHLEN - pos)) {
+    const size_t emergency_filename_length = strlen(buffer);
+    emergency_dump_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, emergency_filename_length + 1);
+    if (NULL == emergency_dump_path) {
+      return NULL;
+    }
+    strncpy(emergency_dump_path, buffer, emergency_filename_length + 1);
+  }
+  if (emergency_dump_path != NULL) {
+    log_info(jfr)( // For user, should not be "jfr, system"
+      "Attempting to recover JFR data, emergency jfr file: %s", emergency_dump_path);
+  }
+  return emergency_dump_path;
+}
+
+// Caller needs ResourceMark
+static const char* create_emergency_chunk_path(const char* repository_path) {
+  assert(repository_path != NULL, "invariant");
+  assert(JfrStream_lock->owned_by_self(), "invariant");
+  const size_t repository_path_len = strlen(repository_path);
+  // date time
+  char date_time_buffer[32] = { 0 };
+  date_time(date_time_buffer, sizeof(date_time_buffer));
+  size_t date_time_len = strlen(date_time_buffer);
+  size_t chunkname_max_len = repository_path_len          // repository_base_path
+                             + 1                          // "/"
+                             + date_time_len              // date_time
+                             + strlen(chunk_file_jfr_ext) // .jfr
+                             + 1;
+  char* chunk_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, chunkname_max_len);
+  if (chunk_path == NULL) {
+    return NULL;
+  }
+  // append the individual substrings
+  jio_snprintf(chunk_path, chunkname_max_len, "%s%s%s%s", repository_path_len, os::file_separator(), date_time_buffer, chunk_file_jfr_ext);
+  return chunk_path;
+}
+
+static fio_fd emergency_dump_file_descriptor() {
+  assert(JfrStream_lock->owned_by_self(), "invariant");
+  ResourceMark rm;
+  const char* const emergency_dump_path = create_emergency_dump_path();
+  return emergency_dump_path != NULL ? open_exclusivly(emergency_dump_path) : invalid_fd;
+}
+
+const char* JfrEmergencyDump::build_dump_path(const char* repository_path) {
+  return repository_path == NULL ? create_emergency_dump_path() : create_emergency_chunk_path(repository_path);
+}
+
+void JfrEmergencyDump::on_vm_error(const char* repository_path) {
+  assert(repository_path != NULL, "invariant");
+  ResourceMark rm;
+  MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
+  const fio_fd emergency_fd = emergency_dump_file_descriptor();
+  if (emergency_fd != invalid_fd) {
+    RepositoryIterator iterator(repository_path, strlen(repository_path));
+    write_emergency_file(emergency_fd, iterator);
+    os::close(emergency_fd);
+  }
+}
 
 /*
 * We are just about to exit the VM, so we will be very aggressive
--- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -33,6 +33,8 @@
 class JfrEmergencyDump : AllStatic {
  public:
   static void on_vm_shutdown(bool exception_handler);
+  static void on_vm_error(const char* repository_path);
+  static const char* build_dump_path(const char* repository_path);
 };
 
 #endif // SHARE_JFR_RECORDER_REPOSITORY_JFREMERGENCYDUMP_HPP
--- a/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/jfr/recorder/repository/jfrRepository.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -28,12 +28,11 @@
 #include "jfr/recorder/jfrRecorder.hpp"
 #include "jfr/recorder/repository/jfrChunkState.hpp"
 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
+#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
 #include "jfr/recorder/repository/jfrRepository.hpp"
 #include "jfr/recorder/service/jfrPostBox.hpp"
-#include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/mutex.hpp"
-#include "runtime/os.hpp"
 #include "runtime/thread.inline.hpp"
 
 static JfrRepository* _instance = NULL;
@@ -84,321 +83,13 @@
   _instance = NULL;
 }
 
-static const char vm_error_filename_fmt[] = "hs_err_pid%p.jfr";
-static const char vm_oom_filename_fmt[] = "hs_oom_pid%p.jfr";
-static const char vm_soe_filename_fmt[] = "hs_soe_pid%p.jfr";
-static const char chunk_file_jfr_ext[] = ".jfr";
-static const size_t iso8601_len = 19; // "YYYY-MM-DDTHH:MM:SS"
-
-static fio_fd open_exclusivly(const char* path) {
-  return os::open(path, O_CREAT | O_WRONLY, S_IREAD | S_IWRITE);
-}
-
-static fio_fd open_existing(const char* path) {
-  return os::open(path, O_RDWR, S_IREAD | S_IWRITE);
-}
-
-static int file_sort(const char** const file1, const char** file2) {
-  assert(NULL != *file1 && NULL != *file2, "invariant");
-  int cmp = strncmp(*file1, *file2, iso8601_len);
-  if (0 == cmp) {
-    const char* const dot1 = strchr(*file1, '.');
-    assert(NULL != dot1, "invariant");
-    const char* const dot2 = strchr(*file2, '.');
-    assert(NULL != dot2, "invariant");
-    ptrdiff_t file1_len = dot1 - *file1;
-    ptrdiff_t file2_len = dot2 - *file2;
-    if (file1_len < file2_len) {
-      return -1;
-    }
-    if (file1_len > file2_len) {
-      return 1;
-    }
-    assert(file1_len == file2_len, "invariant");
-    cmp = strncmp(*file1, *file2, file1_len);
-  }
-  assert(cmp != 0, "invariant");
-  return cmp;
-}
-
-static void iso8601_to_date_time(char* iso8601_str) {
-  assert(iso8601_str != NULL, "invariant");
-  assert(strlen(iso8601_str) == iso8601_len, "invariant");
-  // "YYYY-MM-DDTHH:MM:SS"
-  for (size_t i = 0; i < iso8601_len; ++i) {
-    switch(iso8601_str[i]) {
-      case 'T' :
-      case '-' :
-      case ':' :
-        iso8601_str[i] = '_';
-        break;
-    }
-  }
-  // "YYYY_MM_DD_HH_MM_SS"
-}
-
-static void date_time(char* buffer, size_t buffer_len) {
-  assert(buffer != NULL, "invariant");
-  assert(buffer_len >= iso8601_len, "buffer too small");
-  os::iso8601_time(buffer, buffer_len);
-  assert(strlen(buffer) >= iso8601_len + 1, "invariant");
-  // "YYYY-MM-DDTHH:MM:SS"
-  buffer[iso8601_len] = '\0';
-  iso8601_to_date_time(buffer);
-}
-
-static int64_t file_size(fio_fd fd) {
-  assert(fd != invalid_fd, "invariant");
-  const int64_t current_offset = os::current_file_offset(fd);
-  const int64_t size = os::lseek(fd, 0, SEEK_END);
-  os::seek_to_file_offset(fd, current_offset);
-  return size;
-}
-
-class RepositoryIterator : public StackObj {
- private:
-  const char* const _repo;
-  const size_t _repository_len;
-  GrowableArray<const char*>* _files;
-  const char* const fully_qualified(const char* entry) const;
-  mutable int _iterator;
-
- public:
-   RepositoryIterator(const char* repository, size_t repository_len);
-   ~RepositoryIterator() {}
-  debug_only(void print_repository_files() const;)
-  const char* const filter(const char* entry) const;
-  bool has_next() const;
-  const char* const next() const;
-};
-
-const char* const RepositoryIterator::fully_qualified(const char* entry) const {
-  assert(NULL != entry, "invariant");
-  char* file_path_entry = NULL;
-   // only use files that have content, not placeholders
-  const char* const file_separator = os::file_separator();
-  if (NULL != file_separator) {
-    const size_t entry_len = strlen(entry);
-    const size_t file_separator_length = strlen(file_separator);
-    const size_t file_path_entry_length = _repository_len + file_separator_length + entry_len;
-    file_path_entry = NEW_RESOURCE_ARRAY_RETURN_NULL(char, file_path_entry_length + 1);
-    if (NULL == file_path_entry) {
-      return NULL;
-    }
-    int position = 0;
-    position += jio_snprintf(&file_path_entry[position], _repository_len + 1, "%s", _repo);
-    position += jio_snprintf(&file_path_entry[position], file_separator_length + 1, "%s", os::file_separator());
-    position += jio_snprintf(&file_path_entry[position], entry_len + 1, "%s", entry);
-    file_path_entry[position] = '\0';
-    assert((size_t)position == file_path_entry_length, "invariant");
-    assert(strlen(file_path_entry) == (size_t)position, "invariant");
-  }
-  return file_path_entry;
-}
-
-const char* const RepositoryIterator::filter(const char* entry) const {
-  if (entry == NULL) {
-    return NULL;
-  }
-  const size_t entry_len = strlen(entry);
-  if (entry_len <= 2) {
-    // for "." and ".."
-    return NULL;
-  }
-  char* entry_name = NEW_RESOURCE_ARRAY_RETURN_NULL(char, entry_len + 1);
-  if (entry_name == NULL) {
-    return NULL;
-  }
-  strncpy(entry_name, entry, entry_len + 1);
-  const char* const fully_qualified_path_entry = fully_qualified(entry_name);
-  if (NULL == fully_qualified_path_entry) {
-    return NULL;
-  }
-  const fio_fd entry_fd = open_existing(fully_qualified_path_entry);
-  if (invalid_fd == entry_fd) {
-    return NULL;
-  }
-  const int64_t entry_size = file_size(entry_fd);
-  os::close(entry_fd);
-  if (0 == entry_size) {
-    return NULL;
-  }
-  return entry_name;
-}
-
-RepositoryIterator::RepositoryIterator(const char* repository, size_t repository_len) :
-  _repo(repository),
-  _repository_len(repository_len),
-  _files(NULL),
-  _iterator(0) {
-  if (NULL != _repo) {
-    assert(strlen(_repo) == _repository_len, "invariant");
-    _files = new GrowableArray<const char*>(10);
-    DIR* dirp = os::opendir(_repo);
-    if (dirp == NULL) {
-      log_error(jfr, system)("Unable to open repository %s", _repo);
-      return;
-    }
-    struct dirent* dentry;
-    while ((dentry = os::readdir(dirp)) != NULL) {
-      const char* const entry_path = filter(dentry->d_name);
-      if (NULL != entry_path) {
-        _files->append(entry_path);
-      }
-    }
-    os::closedir(dirp);
-    if (_files->length() > 1) {
-      _files->sort(file_sort);
-    }
-  }
-}
-
-#ifdef ASSERT
-void RepositoryIterator::print_repository_files() const {
-  while (has_next()) {
-    log_error(jfr, system)( "%s", next());
-  }
-}
-#endif
-
-bool RepositoryIterator::has_next() const {
-  return (_files != NULL && _iterator < _files->length());
-}
-
-const char* const RepositoryIterator::next() const {
-  return _iterator >= _files->length() ? NULL : fully_qualified(_files->at(_iterator++));
-}
-
-static void write_emergency_file(fio_fd emergency_fd, const RepositoryIterator& iterator) {
-  assert(emergency_fd != invalid_fd, "invariant");
-  const size_t size_of_file_copy_block = 1 * M; // 1 mb
-  jbyte* const file_copy_block = NEW_RESOURCE_ARRAY_RETURN_NULL(jbyte, size_of_file_copy_block);
-  if (file_copy_block == NULL) {
-    return;
-  }
- int64_t bytes_written_total = 0;
-  while (iterator.has_next()) {
-    fio_fd current_fd = invalid_fd;
-    const char* const fqn = iterator.next();
-    if (fqn != NULL) {
-      current_fd = open_existing(fqn);
-      if (current_fd != invalid_fd) {
-        const int64_t current_filesize = file_size(current_fd);
-        assert(current_filesize > 0, "invariant");
-        int64_t bytes_read = 0;
-        int64_t bytes_written = 0;
-        while (bytes_read < current_filesize) {
-          const ssize_t read_result = os::read_at(current_fd, file_copy_block, size_of_file_copy_block, bytes_read);
-          if (-1 == read_result) {
-            log_info(jfr) ( // For user, should not be "jfr, system"
-              "Unable to recover JFR data");
-            break;
-          }
-          bytes_read += (int64_t)read_result;
-          assert(bytes_read - bytes_written <= (int64_t)size_of_file_copy_block, "invariant");
-          bytes_written += (int64_t)os::write(emergency_fd, file_copy_block, bytes_read - bytes_written);
-          assert(bytes_read == bytes_written, "invariant");
-        }
-        os::close(current_fd);
-        bytes_written_total += bytes_written;
-      }
-    }
-  }
-}
-
-static const char* create_emergency_dump_path() {
-  assert(JfrStream_lock->owned_by_self(), "invariant");
-  char* buffer = NEW_RESOURCE_ARRAY_RETURN_NULL(char, O_BUFLEN);
-  if (NULL == buffer) {
-    return NULL;
-  }
-  const char* const cwd = os::get_current_directory(buffer, O_BUFLEN);
-  if (NULL == cwd) {
-    return NULL;
-  }
-  size_t pos = strlen(cwd);
-  const int fsep_len = jio_snprintf(&buffer[pos], O_BUFLEN - pos, "%s", os::file_separator());
-  const char* filename_fmt = NULL;
-  // fetch specific error cause
-  switch (JfrJavaSupport::cause()) {
-    case JfrJavaSupport::OUT_OF_MEMORY:
-      filename_fmt = vm_oom_filename_fmt;
-      break;
-    case JfrJavaSupport::STACK_OVERFLOW:
-      filename_fmt = vm_soe_filename_fmt;
-      break;
-    default:
-      filename_fmt = vm_error_filename_fmt;
-  }
-  char* emergency_dump_path = NULL;
-  pos += fsep_len;
-  if (Arguments::copy_expand_pid(filename_fmt, strlen(filename_fmt), &buffer[pos], O_BUFLEN - pos)) {
-    const size_t emergency_filename_length = strlen(buffer);
-    emergency_dump_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, emergency_filename_length + 1);
-    if (NULL == emergency_dump_path) {
-      return NULL;
-    }
-    strncpy(emergency_dump_path, buffer, emergency_filename_length + 1);
-  }
-  return emergency_dump_path;
-}
-
-// Caller needs ResourceMark
-static const char* create_emergency_chunk_path(const char* repository_base, size_t repository_len) {
-  assert(repository_base != NULL, "invariant");
-  assert(JfrStream_lock->owned_by_self(), "invariant");
-  // date time
-  char date_time_buffer[32] = {0};
-  date_time(date_time_buffer, sizeof(date_time_buffer));
-  size_t date_time_len = strlen(date_time_buffer);
-  size_t chunkname_max_len = repository_len               // repository_base
-                             + 1                          // "/"
-                             + date_time_len              // date_time
-                             + strlen(chunk_file_jfr_ext) // .jfr
-                             + 1;
-  char* chunk_path = NEW_RESOURCE_ARRAY_RETURN_NULL(char, chunkname_max_len);
-  if (chunk_path == NULL) {
-    return NULL;
-  }
-  // append the individual substrings
-  jio_snprintf(chunk_path, chunkname_max_len, "%s%s%s%s", repository_base, os::file_separator(), date_time_buffer, chunk_file_jfr_ext);
-  return chunk_path;
-}
-
-static fio_fd emergency_dump_file() {
-  assert(JfrStream_lock->owned_by_self(), "invariant");
-  ResourceMark rm;
-  const char* const emergency_dump_path = create_emergency_dump_path();
-  if (emergency_dump_path == NULL) {
-    return invalid_fd;
-  }
-  const fio_fd fd = open_exclusivly(emergency_dump_path);
-  if (fd != invalid_fd) {
-    log_info(jfr)( // For user, should not be "jfr, system"
-      "Attempting to recover JFR data, emergency jfr file: %s", emergency_dump_path);
-  }
-  return fd;
-}
-
-static const char* emergency_path(const char* repository, size_t repository_len) {
-  return repository == NULL ? create_emergency_dump_path() : create_emergency_chunk_path(repository, repository_len);
-}
-
 void JfrRepository::on_vm_error() {
   assert(!JfrStream_lock->owned_by_self(), "invariant");
-  const char* path = _path;
-  if (path == NULL) {
+  if (_path == NULL) {
     // completed already
     return;
   }
-  ResourceMark rm;
-  MutexLockerEx stream_lock(JfrStream_lock, Mutex::_no_safepoint_check_flag);
-  const fio_fd emergency_fd = emergency_dump_file();
-  if (emergency_fd != invalid_fd) {
-    RepositoryIterator iterator(path, strlen(path));
-    write_emergency_file(emergency_fd, iterator);
-    os::close(emergency_fd);
-  }
+  JfrEmergencyDump::on_vm_error(_path);
 }
 
 bool JfrRepository::set_path(const char* path) {
@@ -467,10 +158,7 @@
   assert(JfrStream_lock->owned_by_self(), "invariant");
   if (vm_error) {
     ResourceMark rm;
-    const char* repository_path = _path;
-    const size_t repository_path_len = repository_path != NULL ? strlen(repository_path) : 0;
-    const char* const path = emergency_path(repository_path, repository_path_len);
-    _chunkwriter->set_chunk_path(path);
+    _chunkwriter->set_chunk_path(JfrEmergencyDump::build_dump_path(_path));
   }
   return _chunkwriter->open();
 }
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -93,7 +93,7 @@
     static int _max_oop_map_stack_offset;
     static int _fields_annotations_base_offset;
 
-    static jbyte* cardtable_start_address;
+    static CardTable::CardValue* cardtable_start_address;
     static int cardtable_shift;
 
     static int vm_page_size;
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -24,6 +24,7 @@
 // no precompiled headers
 #include "ci/ciUtilities.hpp"
 #include "gc/shared/barrierSet.hpp"
+#include "gc/shared/cardTable.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/objArrayOop.inline.hpp"
 #include "jvmci/jvmciRuntime.hpp"
@@ -63,7 +64,7 @@
 int CompilerToVM::Data::_max_oop_map_stack_offset;
 int CompilerToVM::Data::_fields_annotations_base_offset;
 
-jbyte* CompilerToVM::Data::cardtable_start_address;
+CardTable::CardValue* CompilerToVM::Data::cardtable_start_address;
 int CompilerToVM::Data::cardtable_shift;
 
 int CompilerToVM::Data::vm_page_size;
@@ -126,7 +127,7 @@
 
   BarrierSet* bs = BarrierSet::barrier_set();
   if (bs->is_a(BarrierSet::CardTableBarrierSet)) {
-    jbyte* base = ci_card_table_address();
+    CardTable::CardValue* base = ci_card_table_address();
     assert(base != NULL, "unexpected byte_map_base");
     cardtable_start_address = base;
     cardtable_shift = CardTable::card_shift;
--- a/src/hotspot/share/memory/heapInspection.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/memory/heapInspection.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -121,6 +121,11 @@
 }
 
 KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) {
+  // Can happen if k is an archived class that we haven't loaded yet.
+  if (k->java_mirror() == NULL) {
+    return NULL;
+  }
+
   KlassInfoEntry* elt = _list;
   while (elt != NULL) {
     if (elt->is_equal(k)) {
@@ -202,7 +207,8 @@
   assert(_buckets != NULL, "Allocation failure should have been caught");
   KlassInfoEntry*  e   = _buckets[idx].lookup(k);
   // Lookup may fail if this is a new klass for which we
-  // could not allocate space for an new entry.
+  // could not allocate space for an new entry, or if it's
+  // an archived class that we haven't loaded yet.
   assert(e == NULL || k == e->klass(), "must be equal");
   return e;
 }
--- a/src/hotspot/share/memory/heapShared.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/memory/heapShared.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -68,6 +68,7 @@
   {"java/lang/Byte$ByteCache",                 "archivedCache"},
   {"java/lang/Short$ShortCache",               "archivedCache"},
   {"java/lang/Character$CharacterCache",       "archivedCache"},
+  {"java/util/jar/Attributes$Name",            "KNOWN_NAMES"},
 };
 // Entry fields for subgraphs archived in the open archive heap region.
 static ArchivableStaticFieldInfo open_archive_subgraph_entry_fields[] = {
--- a/src/hotspot/share/memory/iterator.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/memory/iterator.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -36,6 +36,7 @@
 class KlassClosure;
 class ClassLoaderData;
 class Symbol;
+class Metadata;
 
 // The following classes are C++ `closures` for iterating over objects, roots and spaces
 
@@ -124,6 +125,11 @@
   virtual void do_cld(ClassLoaderData* cld) = 0;
 };
 
+class MetadataClosure : public Closure {
+ public:
+  virtual void do_metadata(Metadata* md) = 0;
+};
+
 
 class CLDToOopClosure : public CLDClosure {
   OopClosure*       _oop_closure;
--- a/src/hotspot/share/oops/instanceKlass.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -3367,7 +3367,9 @@
   if (cfs != NULL) {
     if (cfs->source() != NULL) {
       if (module_name != NULL) {
-        if (ClassLoader::is_modules_image(cfs->source())) {
+        // When the boot loader created the stream, it didn't know the module name
+        // yet. Let's format it now.
+        if (cfs->from_boot_loader_modules_image()) {
           info_stream.print(" source: jrt:/%s", module_name);
         } else {
           info_stream.print(" source: %s", cfs->source());
--- a/src/hotspot/share/oops/symbol.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/oops/symbol.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -264,6 +264,30 @@
   }
 }
 
+void Symbol::make_permanent() {
+  uint32_t found = _length_and_refcount;
+  while (true) {
+    uint32_t old_value = found;
+    int refc = extract_refcount(old_value);
+    if (refc == PERM_REFCOUNT) {
+      return;  // refcount is permanent, permanent is sticky
+    } else if (refc == 0) {
+#ifdef ASSERT
+      print();
+      fatal("refcount underflow");
+#endif
+      return;
+    } else {
+      int len = extract_length(old_value);
+      found = Atomic::cmpxchg(pack_length_and_refcount(len, PERM_REFCOUNT), &_length_and_refcount, old_value);
+      if (found == old_value) {
+        return;  // successfully updated.
+      }
+      // refcount changed, try again.
+    }
+  }
+}
+
 void Symbol::metaspace_pointers_do(MetaspaceClosure* it) {
   if (log_is_enabled(Trace, cds)) {
     LogStream trace_stream(Log(cds)::trace());
--- a/src/hotspot/share/oops/symbol.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/oops/symbol.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -170,6 +170,7 @@
   bool is_permanent() {
     return (refcount() == PERM_REFCOUNT);
   }
+  void make_permanent();
 
   // Function char_at() returns the Symbol's selected u1 byte as a char type.
   //
--- a/src/hotspot/share/opto/library_call.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/opto/library_call.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -2407,7 +2407,7 @@
   }
 
   // Can base be NULL? Otherwise, always on-heap access.
-  bool can_access_non_heap = TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop));
+  bool can_access_non_heap = TypePtr::NULL_PTR->higher_equal(_gvn.type(base));
 
   if (!can_access_non_heap) {
     decorators |= IN_HEAP;
--- a/src/hotspot/share/opto/loopnode.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/opto/loopnode.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1593,12 +1593,17 @@
     } else {
       new_limit = igvn->transform(new SubINode(iv_phi, min));
     }
-    Node* cmp = inner_cle->cmp_node()->clone();
-    igvn->replace_input_of(cmp, 2, new_limit);
-    Node* bol = inner_cle->in(CountedLoopEndNode::TestValue)->clone();
-    cmp->set_req(2, limit);
-    bol->set_req(1, igvn->transform(cmp));
-    igvn->replace_input_of(outer_loop_end(), 1, igvn->transform(bol));
+    Node* inner_cmp = inner_cle->cmp_node();
+    Node* inner_bol = inner_cle->in(CountedLoopEndNode::TestValue);
+    Node* outer_bol = inner_bol;
+    // cmp node for inner loop may be shared
+    inner_cmp = inner_cmp->clone();
+    inner_cmp->set_req(2, new_limit);
+    inner_bol = inner_bol->clone();
+    inner_bol->set_req(1, igvn->transform(inner_cmp));
+    igvn->replace_input_of(inner_cle, CountedLoopEndNode::TestValue, igvn->transform(inner_bol));
+    // Set the outer loop's exit condition too
+    igvn->replace_input_of(outer_loop_end(), 1, outer_bol);
   } else {
     assert(false, "should be able to adjust outer loop");
     IfNode* outer_le = outer_loop_end();
--- a/src/hotspot/share/opto/matcher.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/opto/matcher.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -416,14 +416,20 @@
   return rms;
 }
 
-//---------------------------init_first_stack_mask-----------------------------
+#define NOF_STACK_MASKS (3*6+5)
+
 // Create the initial stack mask used by values spilling to the stack.
 // Disallow any debug info in outgoing argument areas by setting the
 // initial mask accordingly.
 void Matcher::init_first_stack_mask() {
 
   // Allocate storage for spill masks as masks for the appropriate load type.
-  RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * (3*6+5));
+  RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask) * NOF_STACK_MASKS);
+
+  // Initialize empty placeholder masks into the newly allocated arena
+  for (int i = 0; i < NOF_STACK_MASKS; i++) {
+    new (rms + i) RegMask();
+  }
 
   idealreg2spillmask  [Op_RegN] = &rms[0];
   idealreg2spillmask  [Op_RegI] = &rms[1];
--- a/src/hotspot/share/opto/memnode.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/opto/memnode.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1394,6 +1394,14 @@
         Node* in = mem->in(i);
         Node*  m = optimize_memory_chain(in, t_oop, this, phase);
         if (m == mem) {
+          if (i == 1) {
+            // if the first edge was a loop, check second edge too.
+            // If both are replaceable - we are in an infinite loop
+            Node *n = optimize_memory_chain(mem->in(2), t_oop, this, phase);
+            if (n == mem) {
+              break;
+            }
+          }
           set_req(Memory, mem->in(cnt - i));
           return this; // made change
         }
--- a/src/hotspot/share/opto/type.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/opto/type.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -244,10 +244,6 @@
     case T_DOUBLE:   return TypeD::make(constant.as_double());
     case T_ARRAY:
     case T_OBJECT: {
-        // cases:
-        //   can_be_constant    = (oop not scavengable || ScavengeRootsInCode != 0)
-        //   should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
-        // An oop is not scavengable if it is in the perm gen.
         const Type* con_type = NULL;
         ciObject* oop_constant = constant.as_object();
         if (oop_constant->is_null_object()) {
@@ -3228,15 +3224,17 @@
 // Make a java pointer from an oop constant
 const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_constant) {
   assert(!o->is_null_object(), "null object not yet handled here.");
+
+  const bool make_constant = require_constant || o->should_be_constant();
+
   ciKlass* klass = o->klass();
   if (klass->is_instance_klass()) {
     // Element is an instance
-    if (require_constant) {
-      if (!o->can_be_constant())  return NULL;
-    } else if (!o->should_be_constant()) {
+    if (make_constant) {
+      return TypeInstPtr::make(o);
+    } else {
       return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, 0);
     }
-    return TypeInstPtr::make(o);
   } else if (klass->is_obj_array_klass()) {
     // Element is an object array. Recursively call ourself.
     const TypeOopPtr *etype =
@@ -3245,13 +3243,11 @@
     // We used to pass NotNull in here, asserting that the sub-arrays
     // are all not-null.  This is not true in generally, as code can
     // slam NULLs down in the subarrays.
-    if (require_constant) {
-      if (!o->can_be_constant())  return NULL;
-    } else if (!o->should_be_constant()) {
+    if (make_constant) {
+      return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
+    } else {
       return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
     }
-    const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
-    return arr;
   } else if (klass->is_type_array_klass()) {
     // Element is an typeArray
     const Type* etype =
@@ -3259,13 +3255,11 @@
     const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()));
     // We used to pass NotNull in here, asserting that the array pointer
     // is not-null. That was not true in general.
-    if (require_constant) {
-      if (!o->can_be_constant())  return NULL;
-    } else if (!o->should_be_constant()) {
+    if (make_constant) {
+      return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
+    } else {
       return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
     }
-    const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
-    return arr;
   }
 
   fatal("unhandled object type");
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -28,7 +28,6 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
-#include "code/codeCache.hpp"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "logging/log.hpp"
 #include "memory/allocation.inline.hpp"
@@ -3044,11 +3043,6 @@
   blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
   Universe::oops_do(&blk);
 
-  // If there are any non-perm roots in the code cache, visit them.
-  blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
-  CodeBlobToOopClosure look_in_blobs(&blk, !CodeBlobToOopClosure::FixRelocations);
-  CodeCache::scavenge_root_nmethods_do(&look_in_blobs);
-
   return true;
 }
 
--- a/src/hotspot/share/runtime/arguments.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/arguments.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -530,6 +530,7 @@
   { "UseMembar",                    JDK_Version::jdk(10), JDK_Version::jdk(12), JDK_Version::undefined() },
   { "CompilationPolicyChoice",      JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() },
   { "FailOverToOldVerifier",        JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::undefined() },
+  { "AllowJNIEnvProxy",             JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) },
   { "ThreadLocalHandshakes",        JDK_Version::jdk(13), JDK_Version::jdk(14), JDK_Version::jdk(15) },
 
   // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
@@ -3918,6 +3919,13 @@
     warning("Setting CompressedClassSpaceSize has no effect when compressed class pointers are not used");
   }
 
+  // Treat the odd case where local verification is enabled but remote
+  // verification is not as if both were enabled.
+  if (BytecodeVerificationLocal && !BytecodeVerificationRemote) {
+    log_info(verification)("Turning on remote verification because local verification is on");
+    FLAG_SET_DEFAULT(BytecodeVerificationRemote, true);
+  }
+
 #ifndef PRODUCT
   if (!LogVMOutput && FLAG_IS_DEFAULT(LogVMOutput)) {
     if (use_vm_log()) {
--- a/src/hotspot/share/runtime/frame.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/frame.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1115,13 +1115,13 @@
 }
 
 
-// call f() on the interpreted Method*s in the stack.
-// Have to walk the entire code cache for the compiled frames Yuck.
-void frame::metadata_do(void f(Metadata*)) {
+// Call f closure on the interpreted Method*s in the stack.
+void frame::metadata_do(MetadataClosure* f) {
+  ResourceMark rm;
   if (is_interpreted_frame()) {
     Method* m = this->interpreter_frame_method();
     assert(m != NULL, "expecting a method in this frame");
-    f(m);
+    f->do_metadata(m);
   }
 }
 
--- a/src/hotspot/share/runtime/frame.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/frame.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -378,7 +378,7 @@
   void nmethods_do(CodeBlobClosure* cf);
 
   // RedefineClasses support for finding live interpreted methods on the stack
-  void metadata_do(void f(Metadata*));
+  void metadata_do(MetadataClosure* f);
 
   // Verification
   void verify(const RegisterMap* map);
--- a/src/hotspot/share/runtime/globals.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/globals.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -371,6 +371,10 @@
           "Generate a lot of safepoints. This works with "                  \
           "GuaranteedSafepointInterval")                                    \
                                                                             \
+  diagnostic(bool, HandshakeALot, false,                                    \
+          "Generate a lot of handshakes. This works with "                  \
+          "GuaranteedSafepointInterval")                                    \
+                                                                            \
   product_pd(bool, BackgroundCompilation,                                   \
           "A thread requesting compilation is not blocked during "          \
           "compilation")                                                    \
@@ -861,7 +865,7 @@
           "by the application (Solaris & Linux only)")                      \
                                                                             \
   product(bool, AllowJNIEnvProxy, false,                                    \
-          "Allow JNIEnv proxies for jdbx")                                  \
+          "(Deprecated) Allow JNIEnv proxies for jdbx")                     \
                                                                             \
   product(bool, RestoreMXCSROnJNICalls, false,                              \
           "Restore MXCSR when returning from JNI calls")                    \
@@ -1234,7 +1238,7 @@
           "exit")                                                           \
                                                                             \
   product(bool, PrintFlagsRanges, false,                                    \
-          "Print VM flags and their ranges and exit VM")                    \
+          "Print VM flags and their ranges")                                \
                                                                             \
   diagnostic(bool, SerializeVMOutput, true,                                 \
           "Use a mutex to serialize output to tty and LogFile")             \
--- a/src/hotspot/share/runtime/signature.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/signature.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -123,15 +123,6 @@
 }
 
 
-void SignatureIterator::dispatch_field() {
-  // no '(', just one (field) type
-  _index = 0;
-  _parameter_index = 0;
-  parse_type();
-  check_signature_end();
-}
-
-
 void SignatureIterator::iterate_parameters() {
   // Parse parameters
   _index = 0;
@@ -196,7 +187,6 @@
         break;
       case done_parm:
         return;
-        break;
       default:
         tty->print_cr("*** parameter is " UINT64_FORMAT, fingerprint & parameter_feature_mask);
         tty->print_cr("*** fingerprint is " PTR64_FORMAT, saved_fingerprint);
@@ -205,7 +195,6 @@
     }
     fingerprint >>= parameter_feature_size;
   }
-  _parameter_index = 0;
 }
 
 
@@ -239,10 +228,7 @@
         break;
       case '[':
         {
-          int begin = ++_index;
-          while (sig->char_at(_index) == '[') {
-            _index++;
-          }
+          while (sig->char_at(++_index) == '[') ;
           if (sig->char_at(_index) == 'L') {
             while (sig->char_at(_index++) != ';') ;
           } else {
@@ -281,16 +267,17 @@
 
 // Implementation of SignatureStream
 SignatureStream::SignatureStream(Symbol* signature, bool is_method) :
-                   _signature(signature), _at_return_type(false) {
+                   _signature(signature), _at_return_type(false), _previous_name(NULL), _names(NULL) {
   _begin = _end = (is_method ? 1 : 0);  // skip first '(' in method signatures
-  _names = new GrowableArray<Symbol*>(10);
   next();
 }
 
 SignatureStream::~SignatureStream() {
   // decrement refcount for names created during signature parsing
-  for (int i = 0; i < _names->length(); i++) {
-    _names->at(i)->decrement_refcount();
+  if (_names != NULL) {
+    for (int i = 0; i < _names->length(); i++) {
+      _names->at(i)->decrement_refcount();
+    }
   }
 }
 
@@ -359,10 +346,35 @@
     end--;
   }
 
+  const char* symbol_chars = (const char*)_signature->base() + begin;
+  int len = end - begin;
+
+  // Quick check for common symbols in signatures
+  assert((vmSymbols::java_lang_String()->utf8_length() == 16 && vmSymbols::java_lang_Object()->utf8_length() == 16), "sanity");
+  if (len == 16 &&
+      strncmp(symbol_chars, "java/lang/", 10) == 0) {
+    if (strncmp("String", symbol_chars + 10, 6) == 0) {
+      return vmSymbols::java_lang_String();
+    } else if (strncmp("Object", symbol_chars + 10, 6) == 0) {
+      return vmSymbols::java_lang_Object();
+    }
+  }
+
+  Symbol* name = _previous_name;
+  if (name != NULL && name->equals(symbol_chars, len)) {
+    return name;
+  }
+
   // Save names for cleaning up reference count at the end of
   // SignatureStream scope.
-  Symbol* name = SymbolTable::new_symbol(_signature, begin, end, CHECK_NULL);
-  _names->push(name);  // save new symbol for decrementing later
+  name = SymbolTable::new_symbol(symbol_chars, len, CHECK_NULL);
+  if (!name->is_permanent()) {
+    if (_names == NULL) {
+      _names = new GrowableArray<Symbol*>(10);
+    }
+    _names->push(name);  // save new symbol for decrementing later
+  }
+  _previous_name = name;
   return name;
 }
 
@@ -418,18 +430,7 @@
   return args_count;
 }
 
-bool SignatureVerifier::is_valid_signature(Symbol* sig) {
-  const char* signature = (const char*)sig->bytes();
-  ssize_t len = sig->utf8_length();
-  if (signature == NULL || signature[0] == '\0' || len < 1) {
-    return false;
-  } else if (signature[0] == '(') {
-    return is_valid_method_signature(sig);
-  } else {
-    return is_valid_type_signature(sig);
-  }
-}
-
+#ifdef ASSERT
 bool SignatureVerifier::is_valid_method_signature(Symbol* sig) {
   const char* method_sig = (const char*)sig->bytes();
   ssize_t len = sig->utf8_length();
@@ -478,11 +479,12 @@
     case 'L':
       for (index = index + 1; index < limit; ++index) {
         char c = type[index];
-        if (c == ';') {
-          return index + 1;
-        }
-        if (invalid_name_char(c)) {
-          return -1;
+        switch (c) {
+          case ';':
+            return index + 1;
+          case '\0': case '.': case '[':
+            return -1;
+          default: ; // fall through
         }
       }
       // fall through
@@ -490,12 +492,4 @@
   }
   return -1;
 }
-
-bool SignatureVerifier::invalid_name_char(char c) {
-  switch (c) {
-    case '\0': case '.': case ';': case '[':
-      return true;
-    default:
-      return false;
-  }
-}
+#endif // ASSERT
--- a/src/hotspot/share/runtime/signature.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/signature.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -90,7 +90,6 @@
   SignatureIterator(Symbol* signature);
 
   // Iteration
-  void dispatch_field();               // dispatches once for field signatures
   void iterate_parameters();           // iterates over parameters only
   void iterate_parameters( uint64_t fingerprint );
   void iterate_returntype();           // iterates over returntype only
@@ -363,8 +362,8 @@
   int          _end;
   BasicType    _type;
   bool         _at_return_type;
-  GrowableArray<Symbol*>* _names;  // symbols created while parsing signature
-
+  Symbol*      _previous_name;     // cache the previously looked up symbol to avoid lookups
+  GrowableArray<Symbol*>* _names;  // symbols created while parsing that need to be dereferenced
  public:
   bool at_return_type() const                    { return _at_return_type; }
   bool is_done() const;
@@ -402,7 +401,7 @@
   bool is_array() const;                         // True if this argument is an array
   BasicType type() const                         { return _type; }
   Symbol* as_symbol(TRAPS);
-  enum FailureMode { ReturnNull, CNFException, NCDFError };
+  enum FailureMode { ReturnNull, NCDFError };
   Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
   oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
   const u1* raw_bytes()  { return _signature->bytes() + _begin; }
@@ -415,17 +414,13 @@
   int reference_parameter_count();
 };
 
+#ifdef ASSERT
 class SignatureVerifier : public StackObj {
   public:
-    // Returns true if the symbol is valid method or type signature
-    static bool is_valid_signature(Symbol* sig);
-
     static bool is_valid_method_signature(Symbol* sig);
     static bool is_valid_type_signature(Symbol* sig);
   private:
-
     static ssize_t is_valid_type(const char*, ssize_t);
-    static bool invalid_name_char(char);
 };
-
+#endif
 #endif // SHARE_RUNTIME_SIGNATURE_HPP
--- a/src/hotspot/share/runtime/thread.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/thread.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -2264,48 +2264,19 @@
 
 void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) {
   //
-  // Check for pending external suspend. Internal suspend requests do
-  // not use handle_special_runtime_exit_condition().
+  // Check for pending external suspend.
   // If JNIEnv proxies are allowed, don't self-suspend if the target
   // thread is not the current thread. In older versions of jdbx, jdbx
   // threads could call into the VM with another thread's JNIEnv so we
   // can be here operating on behalf of a suspended thread (4432884).
   bool do_self_suspend = is_external_suspend_with_lock();
   if (do_self_suspend && (!AllowJNIEnvProxy || this == JavaThread::current())) {
-    //
-    // Because thread is external suspended the safepoint code will count
-    // thread as at a safepoint. This can be odd because we can be here
-    // as _thread_in_Java which would normally transition to _thread_blocked
-    // at a safepoint. We would like to mark the thread as _thread_blocked
-    // before calling java_suspend_self like all other callers of it but
-    // we must then observe proper safepoint protocol. (We can't leave
-    // _thread_blocked with a safepoint in progress). However we can be
-    // here as _thread_in_native_trans so we can't use a normal transition
-    // constructor/destructor pair because they assert on that type of
-    // transition. We could do something like:
-    //
-    // JavaThreadState state = thread_state();
-    // set_thread_state(_thread_in_vm);
-    // {
-    //   ThreadBlockInVM tbivm(this);
-    //   java_suspend_self()
-    // }
-    // set_thread_state(_thread_in_vm_trans);
-    // if (safepoint) block;
-    // set_thread_state(state);
-    //
-    // but that is pretty messy. Instead we just go with the way the
-    // code has worked before and note that this is the only path to
-    // java_suspend_self that doesn't put the thread in _thread_blocked
-    // mode.
-
     frame_anchor()->make_walkable(this);
-    java_suspend_self();
-
-    // We might be here for reasons in addition to the self-suspend request
-    // so check for other async requests.
-  }
-
+    java_suspend_self_with_safepoint_check();
+  }
+
+  // We might be here for reasons in addition to the self-suspend request
+  // so check for other async requests.
   if (check_asyncs) {
     check_and_handle_async_exceptions();
   }
@@ -2424,6 +2395,7 @@
 //       to complete an external suspend request.
 //
 int JavaThread::java_suspend_self() {
+  assert(thread_state() == _thread_blocked, "wrong state for java_suspend_self()");
   int ret = 0;
 
   // we are in the process of exiting so don't suspend
@@ -2471,6 +2443,36 @@
   return ret;
 }
 
+// Helper routine to set up the correct thread state before calling java_suspend_self.
+// This is called when regular thread-state transition helpers can't be used because
+// we can be in various states, in particular _thread_in_native_trans.
+// Because this thread is external suspended the safepoint code will count it as at
+// a safepoint, regardless of what its actual current thread-state is. But
+// is_ext_suspend_completed() may be waiting to see a thread transition from
+// _thread_in_native_trans to _thread_blocked. So we set the thread state directly
+// to _thread_blocked. The problem with setting thread state directly is that a
+// safepoint could happen just after java_suspend_self() returns after being resumed,
+// and the VM thread will see the _thread_blocked state. So we must check for a safepoint
+// after restoring the state to make sure we won't leave while a safepoint is in progress.
+// However, not all initial-states are allowed when performing a safepoint check, as we
+// should never be blocking at a safepoint whilst in those states. Of these 'bad' states
+// only _thread_in_native is possible when executing this code (based on our two callers).
+// A thread that is _thread_in_native is already safepoint-safe and so it doesn't matter
+// whether the VMThread sees the _thread_blocked state, or the _thread_in_native state,
+// and so we don't need the explicit safepoint check.
+
+void JavaThread::java_suspend_self_with_safepoint_check() {
+  assert(this == Thread::current(), "invariant");
+  JavaThreadState state = thread_state();
+  set_thread_state(_thread_blocked);
+  java_suspend_self();
+  set_thread_state(state);
+  InterfaceSupport::serialize_thread_state_with_handler(this);
+  if (state != _thread_in_native) {
+    SafepointMechanism::block_if_requested(this);
+  }
+}
+
 #ifdef ASSERT
 // Verify the JavaThread has not yet been published in the Threads::list, and
 // hence doesn't need protection from concurrent access at this stage.
@@ -2502,32 +2504,10 @@
   // threads could call into the VM with another thread's JNIEnv so we
   // can be here operating on behalf of a suspended thread (4432884).
   if (do_self_suspend && (!AllowJNIEnvProxy || curJT == thread)) {
-    JavaThreadState state = thread->thread_state();
-
-    // We mark this thread_blocked state as a suspend-equivalent so
-    // that a caller to is_ext_suspend_completed() won't be confused.
-    // The suspend-equivalent state is cleared by java_suspend_self().
-    thread->set_suspend_equivalent();
-
-    // If the safepoint code sees the _thread_in_native_trans state, it will
-    // wait until the thread changes to other thread state. There is no
-    // guarantee on how soon we can obtain the SR_lock and complete the
-    // self-suspend request. It would be a bad idea to let safepoint wait for
-    // too long. Temporarily change the state to _thread_blocked to
-    // let the VM thread know that this thread is ready for GC. The problem
-    // of changing thread state is that safepoint could happen just after
-    // java_suspend_self() returns after being resumed, and VM thread will
-    // see the _thread_blocked state. We must check for safepoint
-    // after restoring the state and make sure we won't leave while a safepoint
-    // is in progress.
-    thread->set_thread_state(_thread_blocked);
-    thread->java_suspend_self();
-    thread->set_thread_state(state);
-
-    InterfaceSupport::serialize_thread_state_with_handler(thread);
-  }
-
-  SafepointMechanism::block_if_requested(curJT);
+    thread->java_suspend_self_with_safepoint_check();
+  } else {
+    SafepointMechanism::block_if_requested(curJT);
+  }
 
   if (thread->is_deopt_suspend()) {
     thread->clear_deopt_suspend();
@@ -2948,9 +2928,21 @@
   }
 }
 
+#ifdef ASSERT
+void JavaThread::verify_states_for_handshake() {
+  // This checks that the thread has a correct frame state during a handshake.
+  assert((!has_last_Java_frame() && java_call_counter() == 0) ||
+         (has_last_Java_frame() && java_call_counter() > 0),
+         "unexpected frame info: has_last_frame=%d, java_call_counter=%d",
+         has_last_Java_frame(), java_call_counter());
+}
+#endif
+
 void JavaThread::nmethods_do(CodeBlobClosure* cf) {
   assert((!has_last_Java_frame() && java_call_counter() == 0) ||
-         (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!");
+         (has_last_Java_frame() && java_call_counter() > 0),
+         "unexpected frame info: has_last_frame=%d, java_call_counter=%d",
+         has_last_Java_frame(), java_call_counter());
 
   if (has_last_Java_frame()) {
     // Traverse the execution stack
@@ -2960,7 +2952,7 @@
   }
 }
 
-void JavaThread::metadata_do(void f(Metadata*)) {
+void JavaThread::metadata_do(MetadataClosure* f) {
   if (has_last_Java_frame()) {
     // Traverse the execution stack to call f() on the methods in the stack
     for (StackFrameStream fst(this); !fst.is_done(); fst.next()) {
@@ -4574,7 +4566,7 @@
   }
 }
 
-void Threads::metadata_do(void f(Metadata*)) {
+void Threads::metadata_do(MetadataClosure* f) {
   ALL_JAVA_THREADS(p) {
     p->metadata_do(f);
   }
--- a/src/hotspot/share/runtime/thread.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/thread.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1348,10 +1348,16 @@
   inline void clear_ext_suspended();
 
  public:
-  void java_suspend();
-  void java_resume();
-  int  java_suspend_self();
+  void java_suspend(); // higher-level suspension logic called by the public APIs
+  void java_resume();  // higher-level resume logic called by the public APIs
+  int  java_suspend_self(); // low-level self-suspension mechanics
 
+ private:
+  // mid-level wrapper around java_suspend_self to set up correct state and
+  // check for a pending safepoint at the end
+  void java_suspend_self_with_safepoint_check();
+
+ public:
   void check_and_wait_while_suspended() {
     assert(JavaThread::current() == this, "sanity check");
 
@@ -1866,7 +1872,10 @@
   virtual void nmethods_do(CodeBlobClosure* cf);
 
   // RedefineClasses Support
-  void metadata_do(void f(Metadata*));
+  void metadata_do(MetadataClosure* f);
+
+  // Debug method asserting thread states are correct during a handshake operation.
+  DEBUG_ONLY(void verify_states_for_handshake();)
 
   // Misc. operations
   char* name() const { return (char*)get_thread_name(); }
@@ -2281,7 +2290,7 @@
   static void nmethods_do(CodeBlobClosure* cf);
 
   // RedefineClasses support
-  static void metadata_do(void f(Metadata*));
+  static void metadata_do(MetadataClosure* f);
   static void metadata_handles_do(void f(Metadata*));
 
 #ifdef ASSERT
--- a/src/hotspot/share/runtime/vmStructs.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -539,7 +539,6 @@
      static_field(CodeCache,                   _heaps,                                        GrowableArray<CodeHeap*>*)             \
      static_field(CodeCache,                   _low_bound,                                    address)                               \
      static_field(CodeCache,                   _high_bound,                                   address)                               \
-     static_field(CodeCache,                   _scavenge_root_nmethods,                       nmethod*)                              \
                                                                                                                                      \
   /*******************************/                                                                                                  \
   /* CodeHeap (NOTE: incomplete) */                                                                                                  \
@@ -681,8 +680,6 @@
                                                                                                                                      \
   nonstatic_field(nmethod,                     _entry_bci,                                    int)                                   \
   nonstatic_field(nmethod,                     _osr_link,                                     nmethod*)                              \
-  nonstatic_field(nmethod,                     _scavenge_root_link,                           nmethod*)                              \
-  nonstatic_field(nmethod,                     _scavenge_root_state,                          jbyte)                                 \
   nonstatic_field(nmethod,                     _state,                                        volatile signed char)                  \
   nonstatic_field(nmethod,                     _exception_offset,                             int)                                   \
   nonstatic_field(nmethod,                     _orig_pc_offset,                               int)                                   \
--- a/src/hotspot/share/runtime/vmThread.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/vmThread.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -434,22 +434,35 @@
 static VM_None    safepointALot_op("SafepointALot");
 static VM_Cleanup cleanup_op;
 
-VM_Operation* VMThread::no_op_safepoint(bool check_time) {
+class HandshakeALotTC : public ThreadClosure {
+ public:
+  virtual void do_thread(Thread* thread) {
+#ifdef ASSERT
+    assert(thread->is_Java_thread(), "must be");
+    JavaThread* jt = (JavaThread*)thread;
+    jt->verify_states_for_handshake();
+#endif
+  }
+};
+
+VM_Operation* VMThread::no_op_safepoint() {
+  // Check for handshakes first since we may need to return a VMop.
+  if (HandshakeALot) {
+    HandshakeALotTC haltc;
+    Handshake::execute(&haltc);
+  }
+  // Check for a cleanup before SafepointALot to keep stats correct.
+  long interval_ms = SafepointTracing::time_since_last_safepoint_ms();
+  bool max_time_exceeded = GuaranteedSafepointInterval != 0 &&
+                           (interval_ms >= GuaranteedSafepointInterval);
+  if (max_time_exceeded && SafepointSynchronize::is_cleanup_needed()) {
+    return &cleanup_op;
+  }
   if (SafepointALot) {
     return &safepointALot_op;
   }
-  if (!SafepointSynchronize::is_cleanup_needed()) {
-    return NULL;
-  }
-  if (check_time) {
-    long interval_ms = SafepointTracing::time_since_last_safepoint_ms();
-    bool max_time_exceeded = GuaranteedSafepointInterval != 0 &&
-                             (interval_ms > GuaranteedSafepointInterval);
-    if (!max_time_exceeded) {
-      return NULL;
-    }
-  }
-  return &cleanup_op;
+  // Nothing to be done.
+  return NULL;
 }
 
 void VMThread::loop() {
@@ -491,19 +504,22 @@
           exit(-1);
         }
 
-        if (timedout && (_cur_vm_operation = VMThread::no_op_safepoint(false)) != NULL) {
-          MutexUnlockerEx mul(VMOperationQueue_lock,
-                              Mutex::_no_safepoint_check_flag);
-          // Force a safepoint since we have not had one for at least
-          // 'GuaranteedSafepointInterval' milliseconds.  This will run all
-          // the clean-up processing that needs to be done regularly at a
-          // safepoint
-          SafepointSynchronize::begin();
-          #ifdef ASSERT
+        if (timedout) {
+          // Have to unlock VMOperationQueue_lock just in case no_op_safepoint()
+          // has to do a handshake.
+          MutexUnlockerEx mul(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag);
+          if ((_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) {
+            // Force a safepoint since we have not had one for at least
+            // 'GuaranteedSafepointInterval' milliseconds and we need to clean
+            // something. This will run all the clean-up processing that needs
+            // to be done at a safepoint.
+            SafepointSynchronize::begin();
+            #ifdef ASSERT
             if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot();
-          #endif
-          SafepointSynchronize::end();
-          _cur_vm_operation = NULL;
+            #endif
+            SafepointSynchronize::end();
+            _cur_vm_operation = NULL;
+          }
         }
         _cur_vm_operation = _vm_queue->remove_next();
 
@@ -615,10 +631,9 @@
       VMOperationRequest_lock->notify_all();
     }
 
-    //
-    // We want to make sure that we get to a safepoint regularly.
-    //
-    if ((_cur_vm_operation = VMThread::no_op_safepoint(false)) != NULL) {
+    // We want to make sure that we get to a safepoint regularly
+    // even when executing VMops that don't require safepoints.
+    if ((_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) {
       HandleMark hm(VMThread::vm_thread());
       SafepointSynchronize::begin();
       SafepointSynchronize::end();
--- a/src/hotspot/share/runtime/vmThread.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/runtime/vmThread.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -123,7 +123,7 @@
 
   static VMOperationTimeoutTask* _timeout_task;
 
-  static VM_Operation* no_op_safepoint(bool check_time);
+  static VM_Operation* no_op_safepoint();
 
   void evaluate_operation(VM_Operation* op);
 
--- a/src/hotspot/share/services/heapDumper.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/services/heapDumper.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -958,6 +958,11 @@
 // creates HPROF_GC_INSTANCE_DUMP record for the given object
 void DumperSupport::dump_instance(DumpWriter* writer, oop o) {
   Klass* k = o->klass();
+  if (k->java_mirror() == NULL) {
+    // Ignoring this object since the corresponding java mirror is not loaded.
+    // Might be a dormant archive object.
+    return;
+  }
 
   writer->write_u1(HPROF_GC_INSTANCE_DUMP);
   writer->write_objectID(o);
--- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp	Tue Mar 26 09:05:10 2019 -0400
@@ -270,8 +270,8 @@
 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53017
 //
 // GCC versions older than 4.6.4 would fail even with "+0", and needs additional
-// cast to typeof(x) to work around the similar bug.
+// cast to __typeof__(x) to work around the similar bug.
 //
-#define ATTRIBUTE_ALIGNED(x) __attribute__((aligned((typeof(x))x+0)))
+#define ATTRIBUTE_ALIGNED(x) __attribute__((aligned((__typeof__(x))x+0)))
 
 #endif // SHARE_UTILITIES_GLOBALDEFINITIONS_GCC_HPP
--- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -124,13 +124,13 @@
     /**
      * createSubSystem objects and initialize mount points
      */
-    private static void createSubSystem(Metrics metric, String [] mountentry) {
+    private static void createSubSystem(Metrics metric, String[] mountentry) {
         if (mountentry.length < 5) return;
 
         Path p = Paths.get(mountentry[4]);
-        String subsystemName = p.getFileName().toString();
+        String[] subsystemNames = p.getFileName().toString().split(",");
 
-        if (subsystemName != null) {
+        for (String subsystemName: subsystemNames) {
             switch (subsystemName) {
                 case "memory":
                     metric.setMemorySubSystem(new SubSystem(mountentry[3], mountentry[4]));
@@ -138,11 +138,6 @@
                 case "cpuset":
                     metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4]));
                     break;
-                case "cpu,cpuacct":
-                case "cpuacct,cpu":
-                    metric.setCpuSubSystem(new SubSystem(mountentry[3], mountentry[4]));
-                    metric.setCpuAcctSubSystem(new SubSystem(mountentry[3], mountentry[4]));
-                    break;
                 case "cpuacct":
                     metric.setCpuAcctSubSystem(new SubSystem(mountentry[3], mountentry[4]));
                     break;
@@ -162,7 +157,7 @@
     /**
      * setSubSystemPath based on the contents of /proc/self/cgroup
      */
-    private static void setSubSystemPath(Metrics metric, String [] entry) {
+    private static void setSubSystemPath(Metrics metric, String[] entry) {
         String controller;
         String base;
         SubSystem subsystem = null;
@@ -298,15 +293,15 @@
 
 
     public long getCpuPeriod() {
-        return SubSystem.getLongValue(cpuacct, "cpu.cfs_period_us");
+        return SubSystem.getLongValue(cpu, "cpu.cfs_period_us");
     }
 
     public long getCpuQuota() {
-        return SubSystem.getLongValue(cpuacct, "cpu.cfs_quota_us");
+        return SubSystem.getLongValue(cpu, "cpu.cfs_quota_us");
     }
 
     public long getCpuShares() {
-        long retval = SubSystem.getLongValue(cpuacct, "cpu.shares");
+        long retval = SubSystem.getLongValue(cpu, "cpu.shares");
         if (retval == 0 || retval == 1024)
             return -1;
         else
@@ -314,15 +309,15 @@
     }
 
     public long getCpuNumPeriods() {
-        return SubSystem.getLongEntry(cpuacct, "cpu.stat", "nr_periods");
+        return SubSystem.getLongEntry(cpu, "cpu.stat", "nr_periods");
     }
 
     public long getCpuNumThrottled() {
-        return SubSystem.getLongEntry(cpuacct, "cpu.stat", "nr_throttled");
+        return SubSystem.getLongEntry(cpu, "cpu.stat", "nr_throttled");
     }
 
     public long getCpuThrottledTime() {
-        return SubSystem.getLongEntry(cpuacct, "cpu.stat", "throttled_time");
+        return SubSystem.getLongEntry(cpu, "cpu.stat", "throttled_time");
     }
 
     public long getEffectiveCpuCount() {
--- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java	Tue Mar 26 09:05:10 2019 -0400
@@ -48,7 +48,7 @@
     public void setPath(String cgroupPath) {
         if (root != null && cgroupPath != null) {
             if (root.equals("/")) {
-                if (cgroupPath.equals("/")) {
+                if (!cgroupPath.equals("/")) {
                     path = mountPoint + cgroupPath;
                 }
                 else {
--- a/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -113,12 +113,7 @@
             } else if (keyLength < 0) {
                 throw new InvalidKeySpecException("Key length is negative");
             }
-            this.prf = Mac.getInstance(prfAlgo);
-            // SunPKCS11 requires a non-empty PBE password
-            if (passwdBytes.length == 0 &&
-                    this.prf.getProvider().getName().startsWith("SunPKCS11")) {
-                this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
-            }
+            this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
             this.key = deriveKey(prf, passwdBytes, salt, iterCount, keyLength);
         } catch (NoSuchAlgorithmException nsae) {
             // not gonna happen; re-throw just in case
@@ -207,7 +202,7 @@
                 }
             }
         } catch (GeneralSecurityException gse) {
-            throw new RuntimeException("Error deriving PBKDF2 keys");
+            throw new RuntimeException("Error deriving PBKDF2 keys", gse);
         }
         return key;
     }
--- a/src/java.base/share/classes/com/sun/security/cert/internal/x509/X509V1CertImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/com/sun/security/cert/internal/x509/X509V1CertImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,8 @@
  *
  * @author Jeff Nisewanger
  */
-@Deprecated
+@SuppressWarnings("removal")
+@Deprecated(since="9", forRemoval=true)
 public class X509V1CertImpl extends X509Certificate implements Serializable {
     static final long serialVersionUID = -2048442350420423405L;
     private java.security.cert.X509Certificate wrappedCert;
--- a/src/java.base/share/classes/java/io/DataInput.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/io/DataInput.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
  * may be thrown if the input stream has been
  * closed.
  *
- * <h3><a id="modified-utf-8">Modified UTF-8</a></h3>
+ * <h2><a id="modified-utf-8">Modified UTF-8</a></h2>
  * <p>
  * Implementations of the DataInput and DataOutput interfaces represent
  * Unicode strings in a format that is a slight modification of UTF-8.
--- a/src/java.base/share/classes/java/io/File.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/io/File.java	Tue Mar 26 09:05:10 2019 -0400
@@ -128,7 +128,7 @@
  * created, the abstract pathname represented by a <code>File</code> object
  * will never change.
  *
- * <h3>Interoperability with {@code java.nio.file} package</h3>
+ * <h2>Interoperability with {@code java.nio.file} package</h2>
  *
  * <p> The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a>
  * package defines interfaces and classes for the Java virtual machine to access
--- a/src/java.base/share/classes/java/io/InputStream.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/io/InputStream.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -237,7 +237,7 @@
      * <code>b[off+len-1]</code> unaffected.
      *
      * <p> In every case, elements <code>b[0]</code> through
-     * <code>b[off]</code> and elements <code>b[off+len]</code> through
+     * <code>b[off-1]</code> and elements <code>b[off+len]</code> through
      * <code>b[b.length-1]</code> are unaffected.
      *
      * <p> The <code>read(b,</code> <code>off,</code> <code>len)</code> method
--- a/src/java.base/share/classes/java/lang/Character.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/Character.java	Tue Mar 26 09:05:10 2019 -0400
@@ -44,7 +44,7 @@
  * and for converting characters from uppercase to lowercase and vice
  * versa.
  *
- * <h3><a id="conformance">Unicode Conformance</a></h3>
+ * <h2><a id="conformance">Unicode Conformance</a></h2>
  * <p>
  * The fields and methods of class {@code Character} are defined in terms
  * of character information from the Unicode Standard, specifically the
@@ -59,7 +59,7 @@
  * {@code U+32FF}, from the first version of the Unicode Standard
  * after 11.0 that assigns the code point.
  *
- * <h3><a id="unicode">Unicode Character Representations</a></h3>
+ * <h2><a id="unicode">Unicode Character Representations</a></h2>
  *
  * <p>The {@code char} data type (and therefore the value that a
  * {@code Character} object encapsulates) are based on the
--- a/src/java.base/share/classes/java/lang/ClassLoader.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -126,7 +126,7 @@
  * duration of the class loading process (see {@link #loadClass
  * loadClass} methods).
  *
- * <h3> <a id="builtinLoaders">Run-time Built-in Class Loaders</a></h3>
+ * <h2> <a id="builtinLoaders">Run-time Built-in Class Loaders</a></h2>
  *
  * The Java run-time has the following built-in class loaders:
  *
--- a/src/java.base/share/classes/java/lang/ModuleLayer.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/ModuleLayer.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,7 +120,7 @@
  * in this class causes a {@link NullPointerException NullPointerException} to
  * be thrown. </p>
  *
- * <h3> Example usage: </h3>
+ * <h2> Example usage: </h2>
  *
  * <p> This example creates a configuration by resolving a module named
  * "{@code myapp}" with the configuration for the boot layer as the parent. It
--- a/src/java.base/share/classes/java/lang/Process.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/Process.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -206,20 +206,20 @@
     public boolean waitFor(long timeout, TimeUnit unit)
         throws InterruptedException
     {
-        long startTime = System.nanoTime();
-        long rem = unit.toNanos(timeout);
+        long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions
+        if (hasExited())
+            return true;
+        if (timeout <= 0)
+            return false;
 
+        long deadline = System.nanoTime() + remainingNanos;
         do {
-            try {
-                exitValue();
+            Thread.sleep(Math.min(TimeUnit.NANOSECONDS.toMillis(remainingNanos) + 1, 100));
+            if (hasExited())
                 return true;
-            } catch(IllegalThreadStateException ex) {
-                if (rem > 0)
-                    Thread.sleep(
-                        Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
-            }
-            rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
-        } while (rem > 0);
+            remainingNanos = deadline - System.nanoTime();
+        } while (remainingNanos > 0);
+
         return false;
     }
 
@@ -320,11 +320,20 @@
      * @since 1.8
      */
     public boolean isAlive() {
+        return !hasExited();
+    }
+
+    /**
+     * This is called from the default implementation of
+     * {@code waitFor(long, TimeUnit)}, which is specified to poll
+     * {@code exitValue()}.
+     */
+    private boolean hasExited() {
         try {
             exitValue();
+            return true;
+        } catch (IllegalThreadStateException e) {
             return false;
-        } catch(IllegalThreadStateException e) {
-            return true;
         }
     }
 
--- a/src/java.base/share/classes/java/lang/ThreadGroup.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/ThreadGroup.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 
 import java.io.PrintStream;
 import java.util.Arrays;
-import jdk.internal.misc.VM;
 
 /**
  * A thread group represents a set of threads. In addition, a thread
@@ -425,7 +424,7 @@
         ThreadGroup[] groupsSnapshot = null;
         synchronized (this) {
             if (destroyed) {
-                return 0;
+                return n;
             }
             int nt = nthreads;
             if (nt > list.length - n) {
@@ -559,7 +558,7 @@
         ThreadGroup[] groupsSnapshot = null;
         synchronized (this) {
             if (destroyed) {
-                return 0;
+                return n;
             }
             int ng = ngroups;
             if (ng > list.length - n) {
--- a/src/java.base/share/classes/java/lang/doc-files/ValueBased.html	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/doc-files/ValueBased.html	Tue Mar 26 09:05:10 2019 -0400
@@ -5,7 +5,7 @@
   <link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">
 </head>
 <body>
-<h2 id="ValueBased">Value-based Classes</h2>
+<h1 id="ValueBased">Value-based Classes</h1>
 
 Some classes, such as <code>java.util.Optional</code> and
 <code>java.time.LocalDateTime</code>, are <em>value-based</em>.  Instances of a
--- a/src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/doc-files/threadPrimitiveDeprecation.html	Tue Mar 26 09:05:10 2019 -0400
@@ -1,6 +1,6 @@
 <!doctype html>
 <!--
- Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,9 @@
   <link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">
 </head>
 <body>
-<h2>Java Thread Primitive Deprecation</h2>
+<h1>Java Thread Primitive Deprecation</h1>
 <hr>
-<h3>Why is <code>Thread.stop</code> deprecated?</h3>
+<h2>Why is <code>Thread.stop</code> deprecated?</h2>
 <p>Because it is inherently unsafe. Stopping a thread causes it to
 unlock all the monitors that it has locked. (The monitors are
 unlocked as the <code>ThreadDeath</code> exception propagates up
@@ -46,8 +46,8 @@
 manifest itself at any time after the actual damage occurs, even
 hours or days in the future.</p>
 <hr>
-<h3>Couldn't I just catch the <code>ThreadDeath</code> exception
-and fix the damaged object?</h3>
+<h2>Couldn't I just catch the <code>ThreadDeath</code> exception
+and fix the damaged object?</h2>
 <p>In theory, perhaps, but it would <em>vastly</em> complicate the
 task of writing correct multithreaded code. The task would be
 nearly insurmountable for two reasons:</p>
@@ -62,7 +62,7 @@
 </ol>
 In sum, it just isn't practical.
 <hr>
-<h3>What should I use instead of <code>Thread.stop</code>?</h3>
+<h2>What should I use instead of <code>Thread.stop</code>?</h2>
 <p>Most uses of <code>stop</code> should be replaced by code that
 simply modifies some variable to indicate that the target thread
 should stop running. The target thread should check this variable
@@ -117,8 +117,8 @@
     }
 </pre>
 <hr>
-<h3>How do I stop a thread that waits for long periods (e.g., for
-input)?</h3>
+<h2>How do I stop a thread that waits for long periods (e.g., for
+input)?</h2>
 <p>That's what the <code>Thread.interrupt</code> method is for. The
 same "state based" signaling mechanism shown above can be used, but
 the state change (<code>blinker = null</code>, in the previous
@@ -145,8 +145,8 @@
 This ensures that the Thread will reraise the
 <code>InterruptedException</code> as soon as it is able.
 <hr>
-<h3>What if a thread doesn't respond to
-<code>Thread.interrupt</code>?</h3>
+<h2>What if a thread doesn't respond to
+<code>Thread.interrupt</code>?</h2>
 <p>In some cases, you can use application specific tricks. For
 example, if a thread is waiting on a known socket, you can close
 the socket to cause the thread to return immediately.
@@ -158,8 +158,8 @@
 operations for which thread.stop and thread.interrupt do not work
 properly.</p>
 <hr>
-<h3>Why are <code>Thread.suspend</code> and
-<code>Thread.resume</code> deprecated?</h3>
+<h2>Why are <code>Thread.suspend</code> and
+<code>Thread.resume</code> deprecated?</h2>
 <p><code>Thread.suspend</code> is inherently deadlock-prone. If the
 target thread holds a lock on the monitor protecting a critical
 system resource when it is suspended, no thread can access this
@@ -168,8 +168,8 @@
 to calling <code>resume</code>, deadlock results. Such deadlocks
 typically manifest themselves as "frozen" processes.</p>
 <hr>
-<h3>What should I use instead of <code>Thread.suspend</code> and
-<code>Thread.resume</code>?</h3>
+<h2>What should I use instead of <code>Thread.suspend</code> and
+<code>Thread.resume</code>?</h2>
 <p>As with <code>Thread.stop</code>, the prudent approach is to
 have the "target thread" poll a variable indicating the desired
 state of the thread (active or suspended). When the desired state
@@ -283,8 +283,8 @@
     }
 </pre>
 <hr size="3" noshade="noshade" />
-<h3>Can I combine the two techniques to produce a thread that may
-be safely "stopped" or "suspended"?</h3>
+<h2>Can I combine the two techniques to produce a thread that may
+be safely "stopped" or "suspended"?</h2>
 Yes, it's reasonably straightforward. The one subtlety is that the
 target thread may already be suspended at the time that another
 thread tries to stop it. If the <code>stop</code> method merely sets
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Tue Mar 26 09:05:10 2019 -0400
@@ -52,7 +52,7 @@
  * {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
  * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
  *
- * <h1>Method handle contents</h1>
+ * <h2>Method handle contents</h2>
  * Method handles are dynamically and strongly typed according to their parameter and return types.
  * They are not distinguished by the name or the defining class of their underlying methods.
  * A method handle must be invoked using a symbolic type descriptor which matches
@@ -89,7 +89,7 @@
  * from its specific class, as the method handle class hierarchy (if any)
  * may change from time to time or across implementations from different vendors.
  *
- * <h1>Method handle compilation</h1>
+ * <h2>Method handle compilation</h2>
  * A Java method call expression naming {@code invokeExact} or {@code invoke}
  * can invoke a method handle from Java source code.
  * From the viewpoint of source code, these methods can take any arguments
@@ -121,7 +121,7 @@
  * The ambiguity with the type {@code Void} is harmless, since there are no references of type
  * {@code Void} except the null reference.
  *
- * <h1>Method handle invocation</h1>
+ * <h2>Method handle invocation</h2>
  * The first time an {@code invokevirtual} instruction is executed
  * it is linked by symbolically resolving the names in the instruction
  * and verifying that the method call is statically legal.
@@ -164,7 +164,7 @@
  * (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable,
  * and implementations are therefore not required to materialize it.)
  *
- * <h1>Invocation checking</h1>
+ * <h2>Invocation checking</h2>
  * In typical programs, method handle type matching will usually succeed.
  * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
  * either directly (in the case of {@code invokeExact}) or indirectly as if
@@ -205,7 +205,7 @@
  * They should not be passed to untrusted code unless their use from
  * the untrusted code would be harmless.
  *
- * <h1>Method handle creation</h1>
+ * <h2>Method handle creation</h2>
  * Java code can create a method handle that directly accesses
  * any method, constructor, or field that is accessible to that code.
  * This is done via a reflective, capability-based API called
@@ -263,7 +263,7 @@
  * of an {@code invokevirtual} or {@code invokeinterface} instruction on
  * a private method (as applicable).
  *
- * <h1>Usage examples</h1>
+ * <h2>Usage examples</h2>
  * Here are some examples of usage:
  * <blockquote><pre>{@code
 Object x, y; String s; int i;
@@ -309,7 +309,7 @@
  * be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals}
  * on its arguments, and asserts that the result is true.
  *
- * <h1>Exceptions</h1>
+ * <h2>Exceptions</h2>
  * The methods {@code invokeExact} and {@code invoke} are declared
  * to throw {@link java.lang.Throwable Throwable},
  * which is to say that there is no static restriction on what a method handle
@@ -322,7 +322,7 @@
  * throwables locally, rethrowing only those which are legal in the context,
  * and wrapping ones which are illegal.
  *
- * <h1><a id="sigpoly"></a>Signature polymorphism</h1>
+ * <h2><a id="sigpoly"></a>Signature polymorphism</h2>
  * The unusual compilation and linkage behavior of
  * {@code invokeExact} and plain {@code invoke}
  * is referenced by the term <em>signature polymorphism</em>.
@@ -347,7 +347,7 @@
  * Tools which determine symbolic linkage are required to accept such
  * untransformed descriptors, without reporting linkage errors.
  *
- * <h1>Interoperation between method handles and the Core Reflection API</h1>
+ * <h2>Interoperation between method handles and the Core Reflection API</h2>
  * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
  * any class member represented by a Core Reflection API object
  * can be converted to a behaviorally equivalent method handle.
@@ -389,7 +389,7 @@
  * to call {@code invokeExact} or plain {@code invoke},
  * for any specified type descriptor .
  *
- * <h1>Interoperation between method handles and Java generics</h1>
+ * <h2>Interoperation between method handles and Java generics</h2>
  * A method handle can be obtained on a method, constructor, or field
  * which is declared with Java generic types.
  * As with the Core Reflection API, the type of the method handle
@@ -416,7 +416,7 @@
  * genericity with a Java type parameter.</li>
  * </ul>
  *
- * <h1><a id="maxarity"></a>Arity limits</h1>
+ * <h2><a id="maxarity"></a>Arity limits</h2>
  * The JVM imposes on all methods and constructors of any kind an absolute
  * limit of 255 stacked arguments.  This limit can appear more restrictive
  * in certain cases:
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleInfo.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleInfo.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@
  * A symbolic reference obtained by cracking a direct method handle
  * into its consitutent symbolic parts.
  * To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}.
- * <h1><a id="directmh"></a>Direct Method Handles</h1>
+ * <h2><a id="directmh"></a>Direct Method Handles</h2>
  * A <em>direct method handle</em> represents a method, constructor, or field without
  * any intervening argument bindings or other transformations.
  * The method, constructor, or field referred to by a direct method handle is called
@@ -58,7 +58,7 @@
  *     to convert a {@link Field} into a method handle.
  * </ul>
  *
- * <h1>Restrictions on Cracking</h1>
+ * <h2>Restrictions on Cracking</h2>
  * Given a suitable {@code Lookup} object, it is possible to crack any direct method handle
  * to recover a symbolic reference for the underlying method, constructor, or field.
  * Cracking must be done via a {@code Lookup} object equivalent to that which created
@@ -77,7 +77,7 @@
  * handle with symbolic information (or caller binding) from an unexpected scope.
  * Use {@link java.lang.invoke.MethodHandles#reflectAs} to override this limitation.
  *
- * <h1><a id="refkinds"></a>Reference kinds</h1>
+ * <h2><a id="refkinds"></a>Reference kinds</h2>
  * The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>
  * correspond to all major use cases for methods, constructors, and fields.
  * These use cases may be distinguished using small integers as follows:
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -268,7 +268,7 @@
      * This includes all methods, constructors, and fields which are allowed to the lookup class,
      * even private ones.
      *
-     * <h1><a id="lookups"></a>Lookup Factory Methods</h1>
+     * <h2><a id="lookups"></a>Lookup Factory Methods</h2>
      * The factory methods on a {@code Lookup} object correspond to all major
      * use cases for methods, constructors, and fields.
      * Each method handle created by a factory method is the functional
@@ -395,7 +395,7 @@
      * <a href="MethodHandle.html#maxarity">too many parameters.</a>
      * </ul>
      *
-     * <h1><a id="access"></a>Access checking</h1>
+     * <h2><a id="access"></a>Access checking</h2>
      * Access checks are applied in the factory methods of {@code Lookup},
      * when a method handle is created.
      * This is a key difference from the Core Reflection API, since
@@ -529,7 +529,7 @@
      * whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
      * can be reliably determined and emulated by method handles.
      *
-     * <h1><a id="secmgr"></a>Security manager interactions</h1>
+     * <h2><a id="secmgr"></a>Security manager interactions</h2>
      * Although bytecode instructions can only refer to classes in
      * a related class loader, this API can search for methods in any
      * class, as long as a reference to its {@code Class} object is
@@ -588,7 +588,7 @@
      * or else that is being accessed from a lookup class that has
      * rights to access the member or class.
      *
-     * <h1><a id="callsens"></a>Caller sensitive methods</h1>
+     * <h2><a id="callsens"></a>Caller sensitive methods</h2>
      * A small number of Java methods have a special property called caller sensitivity.
      * A <em>caller-sensitive</em> method can behave differently depending on the
      * identity of its immediate caller.
--- a/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -197,7 +197,7 @@
      * processed before the method returns abnormally.
      * Which elements these are (if any) is implementation-dependent.
      *
-     * <h1>Java Memory Model details</h1>
+     * <h4>Java Memory Model details</h4>
      * In terms of the Java Memory Model, this operation performs a synchronization
      * action which is comparable in effect to the writing of a volatile variable
      * by the current thread, and an eventual volatile read by every other thread
--- a/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Tue Mar 26 09:05:10 2019 -0400
@@ -234,7 +234,7 @@
  * precise phrasing of the specification of access mode methods and memory fence
  * methods may accompany future updates of the Java Language Specification.
  *
- * <h1>Compiling invocation of access mode methods</h1>
+ * <h2>Compiling invocation of access mode methods</h2>
  * A Java method call expression naming an access mode method can invoke a
  * VarHandle from Java source code.  From the viewpoint of source code, these
  * methods can take any arguments and their polymorphic result (if expressed)
@@ -266,7 +266,7 @@
  * except the null reference.
  *
  *
- * <h1><a id="invoke">Performing invocation of access mode methods</a></h1>
+ * <h2><a id="invoke">Performing invocation of access mode methods</a></h2>
  * The first time an {@code invokevirtual} instruction is executed it is linked
  * by symbolically resolving the names in the instruction and verifying that
  * the method call is statically legal.  This also holds for calls to access mode
@@ -329,7 +329,7 @@
  * Where, in this case, the method handle is bound to the VarHandle instance.
  *
  *
- * <h1>Invocation checking</h1>
+ * <h2>Invocation checking</h2>
  * In typical programs, VarHandle access mode type matching will usually
  * succeed.  But if a match fails, the JVM will throw a
  * {@link WrongMethodTypeException}.
@@ -364,7 +364,7 @@
  * untrusted code unless their use from the untrusted code would be harmless.
  *
  *
- * <h1>VarHandle creation</h1>
+ * <h2>VarHandle creation</h2>
  * Java code can create a VarHandle that directly accesses any field that is
  * accessible to that code.  This is done via a reflective, capability-based
  * API called {@link java.lang.invoke.MethodHandles.Lookup
@@ -383,7 +383,7 @@
  * class outside the current package, the receiver argument will be narrowed to
  * the type of the accessing class.
  *
- * <h1>Interoperation between VarHandles and the Core Reflection API</h1>
+ * <h2>Interoperation between VarHandles and the Core Reflection API</h2>
  * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup
  * Lookup} API, any field represented by a Core Reflection API object
  * can be converted to a behaviorally equivalent VarHandle.
@@ -428,7 +428,7 @@
  * any specified access mode type and is equivalent in behaviour to
  * {@link java.lang.invoke.MethodHandles#varHandleInvoker}.
  *
- * <h1>Interoperation between VarHandles and Java generics</h1>
+ * <h2>Interoperation between VarHandles and Java generics</h2>
  * A VarHandle can be obtained for a variable, such as a field, which is
  * declared with Java generic types.  As with the Core Reflection API, the
  * VarHandle's variable type will be constructed from the erasure of the
--- a/src/java.base/share/classes/java/lang/invoke/package-info.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/package-info.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,12 +53,12 @@
  * </li>
  * </ul>
  *
- * <h1><a id="jvm_mods"></a>Dynamic resolution of call sites and constants</h1>
+ * <h2><a id="jvm_mods"></a>Dynamic resolution of call sites and constants</h2>
  * The following low-level information summarizes relevant parts of the
  * Java Virtual Machine specification.  For full details, please see the
  * current version of that specification.
  *
- * <h2><a id="indyinsn"></a>Dynamically-computed call sites</h2>
+ * <h3><a id="indyinsn"></a>Dynamically-computed call sites</h3>
  * An {@code invokedynamic} instruction is originally in an unlinked state.
  * In this state, there is no target method for the instruction to invoke.
  * <p>
@@ -74,7 +74,7 @@
  * The constant pool reference also specifies the invocation's name and method type descriptor,
  * just like {@code invokestatic} and the other invoke instructions.
  *
- * <h2><a id="condycon"></a>Dynamically-computed constants</h2>
+ * <h3><a id="condycon"></a>Dynamically-computed constants</h3>
  * The constant pool may contain constants tagged {@code CONSTANT_Dynamic},
  * equipped with bootstrap methods which perform their resolution.
  * Such a <em>dynamic constant</em> is originally in an unresolved state.
@@ -90,7 +90,7 @@
  * (Roughly speaking, a dynamically-computed constant is to a dynamically-computed call site
  * as a {@code CONSTANT_Fieldref} is to a {@code CONSTANT_Methodref}.)
  *
- * <h2><a id="bsm"></a>Execution of bootstrap methods</h2>
+ * <h3><a id="bsm"></a>Execution of bootstrap methods</h3>
  * Resolving a dynamically-computed call site or constant
  * starts with resolving constants from the constant pool for the
  * following items:
@@ -136,7 +136,7 @@
  * subsequent attempts to execute the {@code invokedynamic} instruction or load the
  * dynamically-computed constant.
  *
- * <h2>Timing of resolution</h2>
+ * <h3>Timing of resolution</h3>
  * An {@code invokedynamic} instruction is linked just before its first execution.
  * A dynamically-computed constant is resolved just before the first time it is used
  * (by pushing it on the stack or linking it as a bootstrap method parameter).
@@ -171,7 +171,7 @@
  * just before its first invocation.
  * There is no way to undo the effect of a completed bootstrap method call.
  *
- * <h2>Types of bootstrap methods</h2>
+ * <h3>Types of bootstrap methods</h3>
  * For a dynamically-computed call site, the bootstrap method is invoked with parameter
  * types {@code MethodHandles.Lookup}, {@code String}, {@code MethodType}, and the types
  * of any static arguments; the return type is {@code CallSite}.
--- a/src/java.base/share/classes/java/lang/module/Configuration.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/module/Configuration.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
  * ModuleLayer.boot().configuration()}. The configuration for the boot layer
  * will often be the parent when creating new configurations. </p>
  *
- * <h3> Example </h3>
+ * <h2> Example </h2>
  *
  * <p> The following example uses the {@link
  * #resolve(ModuleFinder,ModuleFinder,Collection) resolve} method to resolve a
--- a/src/java.base/share/classes/java/lang/module/package-info.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/module/package-info.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
  * will cause a {@code NullPointerException}, unless otherwise specified. </p>
  *
  *
- * <h1><a id="resolution"></a>{@index "Module Resolution"}</h1>
+ * <h2><a id="resolution"></a>{@index "Module Resolution"}</h2>
  *
  * <p> Resolution is the process of computing how modules depend on each other.
  * The process occurs at compile time and run time. </p>
@@ -45,7 +45,7 @@
  * The readability graph embodies how modules depend on each other, which in
  * turn controls access across module boundaries. </p>
  *
- * <h2> Step 1: Recursive enumeration </h2>
+ * <h3> Step 1: Recursive enumeration </h3>
  *
  * <p> Recursive enumeration takes a set of module names, looks up each of their
  * module declarations, and for each module declaration, recursively enumerates:
@@ -91,7 +91,7 @@
  *
  * <p> Otherwise, resolution proceeds to step 2. </p>
  *
- * <h2> Step 2: Computing the readability graph </h2>
+ * <h3> Step 2: Computing the readability graph </h3>
  *
  * <p> A 'requires' directive (irrespective of 'transitive') expresses that
  * one module depends on some other module. The effect of the 'transitive'
@@ -147,7 +147,7 @@
  * <p> Otherwise, resolution succeeds, and the result of resolution is the
  * readability graph.
  *
- * <h2> Root modules </h2>
+ * <h3> Root modules </h3>
  *
  * <p> The set of root modules at compile-time is usually the set of modules
  * being compiled. At run-time, the set of root modules is usually the
@@ -158,7 +158,7 @@
  * that is observable on the upgrade module path or among the system modules,
  * and that exports at least one package without qualification. </p>
  *
- * <h2> Observable modules </h2>
+ * <h3> Observable modules </h3>
  *
  * <p> The set of observable modules at both compile-time and run-time is
  * determined by searching several different paths, and also by searching
@@ -183,7 +183,7 @@
  *
  * </ol>
  *
- * <h2> 'requires' directives with 'static' modifier </h2>
+ * <h3> 'requires' directives with 'static' modifier </h3>
  *
  * <p> 'requires' directives that have the 'static' modifier express an optional
  * dependence at run time. If a module declares that it 'requires static M' then
@@ -191,7 +191,7 @@
  * However, if M is recursively enumerated at step 1 then all modules that are
  * enumerated and `requires static M` will read M. </p>
  *
- * <h2> Completeness </h2>
+ * <h3> Completeness </h3>
  *
  * <p> Resolution may be partial at compile-time in that the complete transitive
  * closure may not be required to compile a set of modules. Minimally, the
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -156,7 +156,7 @@
  * like they do for instances of {@code java.lang.Object}.
  * </ul>
  *
- * <h3><a id="membership">Package and Module Membership of Proxy Class</a></h3>
+ * <h2><a id="membership">Package and Module Membership of Proxy Class</a></h2>
  *
  * The package and module to which a proxy class belongs are chosen such that
  * the accessibility of the proxy class is in line with the accessibility of
--- a/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,12 +30,16 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
 import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
+import sun.net.PlatformSocketImpl;
 import sun.net.ResourceManager;
 import sun.net.util.SocketExceptions;
 
@@ -46,7 +50,7 @@
  *
  * @author  Steven B. Byrne
  */
-abstract class AbstractPlainSocketImpl extends SocketImpl {
+abstract class AbstractPlainSocketImpl extends SocketImpl implements PlatformSocketImpl {
     /* instance variable for SO_TIMEOUT */
     int timeout;   // timeout in millisec
     // traffic class
@@ -450,15 +454,17 @@
 
     /**
      * Accepts connections.
-     * @param s the connection
+     * @param si the socket impl
      */
-    protected void accept(SocketImpl s) throws IOException {
+    protected void accept(SocketImpl si) throws IOException {
+        si.fd = new FileDescriptor();
         acquireFD();
         try {
-            socketAccept(s);
+            socketAccept(si);
         } finally {
             releaseFD();
         }
+        SocketCleanable.register(si.fd);
     }
 
     /**
@@ -470,8 +476,14 @@
                 throw new IOException("Socket Closed");
             if (shut_rd)
                 throw new IOException("Socket input is shutdown");
-            if (socketInputStream == null)
-                socketInputStream = new SocketInputStream(this);
+            if (socketInputStream == null) {
+                PrivilegedExceptionAction<SocketInputStream> pa = () -> new SocketInputStream(this);
+                try {
+                    socketInputStream = AccessController.doPrivileged(pa);
+                } catch (PrivilegedActionException e) {
+                    throw (IOException) e.getCause();
+                }
+            }
         }
         return socketInputStream;
     }
@@ -489,8 +501,14 @@
                 throw new IOException("Socket Closed");
             if (shut_wr)
                 throw new IOException("Socket output is shutdown");
-            if (socketOutputStream == null)
-                socketOutputStream = new SocketOutputStream(this);
+            if (socketOutputStream == null) {
+                PrivilegedExceptionAction<SocketOutputStream> pa = () -> new SocketOutputStream(this);
+                try {
+                    socketOutputStream = AccessController.doPrivileged(pa);
+                } catch (PrivilegedActionException e) {
+                    throw (IOException) e.getCause();
+                }
+            }
         }
         return socketOutputStream;
     }
@@ -589,15 +607,10 @@
         }
     }
 
-    void reset() throws IOException {
-        if (fd != null) {
-            socketClose();
-        }
-        fd = null;
-        super.reset();
+    void reset() {
+        throw new InternalError("should not get here");
     }
 
-
     /**
      * Shutdown read-half of the socket connection;
      */
--- a/src/java.base/share/classes/java/net/ContentHandler.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/ContentHandler.java	Tue Mar 26 09:05:10 2019 -0400
@@ -47,7 +47,7 @@
  * If no content handler could be {@linkplain URLConnection#getContent() found},
  * URLConnection will look for a content handler in a user-definable set of places.
  * Users can define a vertical-bar delimited set of class prefixes
- * to search through by defining the <i>{@link java.net.URLConnection#contentPathProp}</i>
+ * to search through by defining the <i>{@value java.net.URLConnection#contentPathProp}</i>
  * property. The class name must be of the form:
  * <blockquote>
  *     <i>{package-prefix}.{major}.{minor}</i>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/net/DelegatingSocketImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 java.net;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Objects;
+import java.util.Set;
+
+import sun.net.PlatformSocketImpl;
+
+/**
+ * A SocketImpl that delegates all methods to another SocketImpl.
+ */
+
+class DelegatingSocketImpl extends SocketImpl {
+    protected final SocketImpl delegate;
+
+    DelegatingSocketImpl(SocketImpl delegate) {
+        assert delegate instanceof PlatformSocketImpl;
+        this.delegate = Objects.requireNonNull(delegate);
+    }
+
+    final SocketImpl delegate() {
+        return delegate;
+    }
+
+    @Override
+    protected FileDescriptor getFileDescriptor() {
+        return delegate.getFileDescriptor();
+    }
+
+    @Override
+    protected InetAddress getInetAddress() {
+        return delegate.getInetAddress();
+    }
+
+    @Override
+    protected int getPort() {
+        return delegate.getPort();
+    }
+
+    @Override
+    protected int getLocalPort() {
+        return delegate.getLocalPort();
+    }
+
+    @Override
+    protected void create(boolean stream) throws IOException {
+        delegate.create(stream);
+    }
+
+    @Override
+    protected void connect(String host, int port) throws IOException {
+        delegate.connect(host, port);
+    }
+
+    @Override
+    protected void connect(InetAddress address, int port) throws IOException {
+        delegate.connect(address, port);
+    }
+
+    @Override
+    protected void connect(SocketAddress address, int timeout) throws IOException {
+        delegate.connect(address, timeout);
+    }
+
+    @Override
+    protected void bind(InetAddress host, int port) throws IOException {
+        delegate.bind(host, port);
+    }
+
+    @Override
+    protected void listen(int backlog) throws IOException {
+        delegate.listen(backlog);
+    }
+
+    @Override
+    protected void accept(SocketImpl s) throws IOException {
+        delegate.accept(s);
+    }
+
+    @Override
+    protected InputStream getInputStream() throws IOException {
+        return delegate.getInputStream();
+    }
+
+    @Override
+    protected OutputStream getOutputStream() throws IOException {
+        return delegate.getOutputStream();
+    }
+
+    @Override
+    protected int available() throws IOException {
+        return delegate.available();
+    }
+
+    @Override
+    protected void close() throws IOException {
+        delegate.close();
+    }
+
+    @Override
+    protected boolean supportsUrgentData() {
+        return delegate.supportsUrgentData();
+    }
+
+    @Override
+    protected void sendUrgentData(int data) throws IOException {
+        delegate.sendUrgentData(data);
+    }
+
+    @Override
+    protected Set<SocketOption<?>> supportedOptions() {
+        return delegate.supportedOptions();
+    }
+
+    @Override
+    protected <T> void setOption(SocketOption<T> opt, T value) throws IOException {
+        delegate.setOption(opt, value);
+    }
+
+    @Override
+    protected <T> T getOption(SocketOption<T> opt) throws IOException {
+        return delegate.getOption(opt);
+    }
+
+    @Override
+    public void setOption(int optID, Object value) throws SocketException {
+        delegate.setOption(optID, value);
+    }
+
+    @Override
+    public Object getOption(int optID) throws SocketException {
+        return delegate.getOption(optID);
+    }
+
+    @Override
+    protected void shutdownInput() throws IOException {
+        delegate.shutdownInput();
+    }
+
+    @Override
+    protected void shutdownOutput() throws IOException {
+        delegate.shutdownOutput();
+    }
+}
--- a/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,14 +34,13 @@
 
 /**
  * Basic SocketImpl that relies on the internal HTTP protocol handler
- * implementation to perform the HTTP tunneling and authentication. The
- * sockets impl is swapped out and replaced with the socket from the HTTP
- * handler after the tunnel is successfully setup.
+ * implementation to perform the HTTP tunneling and authentication. Once
+ * connected, all socket operations delegate to a platform SocketImpl.
  *
  * @since 1.8
  */
 
-/*package*/ class HttpConnectSocketImpl extends PlainSocketImpl {
+/*package*/ class HttpConnectSocketImpl extends DelegatingSocketImpl {
 
     private static final String httpURLClazzStr =
                                   "sun.net.www.protocol.http.HttpURLConnection";
@@ -76,12 +75,8 @@
         }
     }
 
-    HttpConnectSocketImpl(String server, int port) {
-        this.server = server;
-        this.port = port;
-    }
-
-    HttpConnectSocketImpl(Proxy proxy) {
+    HttpConnectSocketImpl(Proxy proxy, SocketImpl delegate) {
+        super(delegate);
         SocketAddress a = proxy.address();
         if ( !(a instanceof InetSocketAddress) )
             throw new IllegalArgumentException("Unsupported address type");
@@ -92,20 +87,44 @@
     }
 
     @Override
+    protected void connect(String host, int port) throws IOException {
+        connect(new InetSocketAddress(host, port), 0);
+    }
+
+    @Override
+    protected void connect(InetAddress address, int port) throws IOException {
+        connect(new InetSocketAddress(address, port), 0);
+    }
+
+    @Override
+    void setSocket(Socket socket) {
+        delegate.socket = socket;
+        super.setSocket(socket);
+    }
+
+    @Override
+    void setServerSocket(ServerSocket socket) {
+        throw new InternalError("should not get here");
+    }
+
+    @Override
     protected void connect(SocketAddress endpoint, int timeout)
         throws IOException
     {
         if (endpoint == null || !(endpoint instanceof InetSocketAddress))
             throw new IllegalArgumentException("Unsupported address type");
         final InetSocketAddress epoint = (InetSocketAddress)endpoint;
-        final String destHost = epoint.isUnresolved() ? epoint.getHostName()
-                                                      : epoint.getAddress().getHostAddress();
+        String destHost = epoint.isUnresolved() ? epoint.getHostName()
+                                                : epoint.getAddress().getHostAddress();
         final int destPort = epoint.getPort();
 
         SecurityManager security = System.getSecurityManager();
         if (security != null)
             security.checkConnect(destHost, destPort);
 
+        if (destHost.contains(":"))
+            destHost = "[" + destHost + "]";
+
         // Connect to the HTTP proxy server
         String urlString = "http://" + destHost + ":" + destPort;
         Socket httpSocket = privilegedDoTunnel(urlString, timeout);
@@ -117,21 +136,37 @@
         close();
 
         // update the Sockets impl to the impl from the http Socket
-        AbstractPlainSocketImpl psi = (AbstractPlainSocketImpl) httpSocket.impl;
-        this.getSocket().impl = psi;
+        SocketImpl si = httpSocket.impl;
+        getSocket().setImpl(si);
 
         // best effort is made to try and reset options previously set
         Set<Map.Entry<Integer,Object>> options = optionsMap.entrySet();
         try {
             for(Map.Entry<Integer,Object> entry : options) {
-                psi.setOption(entry.getKey(), entry.getValue());
+                si.setOption(entry.getKey(), entry.getValue());
             }
         } catch (IOException x) {  /* gulp! */  }
     }
 
+
+    @Override
+    protected void listen(int backlog) {
+        throw new InternalError("should not get here");
+    }
+
+    @Override
+    protected void accept(SocketImpl s) {
+        throw new InternalError("should not get here");
+    }
+
+    @Override
+    void reset() {
+        throw new InternalError("should not get here");
+    }
+
     @Override
     public void setOption(int opt, Object val) throws SocketException {
-        super.setOption(opt, val);
+        delegate.setOption(opt, val);
 
         if (external_address != null)
             return;  // we're connected, just return
@@ -163,7 +198,10 @@
         URL destURL = new URL(urlString);
         HttpURLConnection conn = (HttpURLConnection) destURL.openConnection(proxy);
         conn.setConnectTimeout(connectTimeout);
-        conn.setReadTimeout(this.timeout);
+        int timeout = (int) getOption(SocketOptions.SO_TIMEOUT);
+        if (timeout > 0) {
+            conn.setReadTimeout(timeout);
+        }
         conn.connect();
         doTunneling(conn);
         try {
@@ -174,10 +212,14 @@
         }
     }
 
-    private void doTunneling(HttpURLConnection conn) {
+    private void doTunneling(HttpURLConnection conn) throws IOException {
         try {
             doTunneling.invoke(conn);
         } catch (ReflectiveOperationException x) {
+            Throwable cause = x.getCause();
+            if (cause instanceof IOException) {
+                throw (IOException) cause;
+            }
             throw new InternalError("Should not reach here", x);
         }
     }
@@ -187,7 +229,7 @@
         if (external_address != null)
             return external_address.getAddress();
         else
-            return super.getInetAddress();
+            return delegate.getInetAddress();
     }
 
     @Override
@@ -195,6 +237,6 @@
         if (external_address != null)
             return external_address.getPort();
         else
-            return super.getPort();
+            return delegate.getPort();
     }
 }
--- a/src/java.base/share/classes/java/net/Inet4Address.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/Inet4Address.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
  * and <a href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC&nbsp;2365:
  * Administratively Scoped IP Multicast</i></a>
  *
- * <h3> <a id="format">Textual representation of IP addresses</a> </h3>
+ * <h2> <a id="format">Textual representation of IP addresses</a> </h2>
  *
  * Textual representation of IPv4 address used as input to methods
  * takes one of the following forms:
@@ -70,7 +70,7 @@
  * <p> For methods that return a textual representation as output
  * value, the first form, i.e. a dotted-quad string, is used.
  *
- * <h4> The Scope of a Multicast Address </h4>
+ * <h3> The Scope of a Multicast Address </h3>
  *
  * Historically the IPv4 TTL field in the IP header has doubled as a
  * multicast scope field: a TTL of 0 means node-local, 1 means
--- a/src/java.base/share/classes/java/net/Inet6Address.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/Inet6Address.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
  * Defined by <a href="http://www.ietf.org/rfc/rfc2373.txt">
  * <i>RFC&nbsp;2373: IP Version 6 Addressing Architecture</i></a>.
  *
- * <h3> <a id="format">Textual representation of IP addresses</a> </h3>
+ * <h2> <a id="format">Textual representation of IP addresses</a> </h2>
  *
  * Textual representation of IPv6 address used as input to methods
  * takes one of the following forms:
@@ -116,7 +116,7 @@
  * form because it is unambiguous when used in combination with other
  * textual data.
  *
- * <h4> Special IPv6 address </h4>
+ * <h3> Special IPv6 address </h3>
  *
  * <blockquote>
  * <table class="borderless">
@@ -135,7 +135,7 @@
  *         address.</td></tr>
  * </table></blockquote>
  *
- * <h4><a id="scoped">Textual representation of IPv6 scoped addresses</a></h4>
+ * <h3><a id="scoped">Textual representation of IPv6 scoped addresses</a></h3>
  *
  * <p> The textual representation of IPv6 addresses as described above can be
  * extended to specify IPv6 scoped addresses. This extension to the basic
--- a/src/java.base/share/classes/java/net/InetAddress.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/InetAddress.java	Tue Mar 26 09:05:10 2019 -0400
@@ -71,7 +71,7 @@
  * with a host name or whether it has already done reverse host name
  * resolution).
  *
- * <h3> Address types </h3>
+ * <h2> Address types </h2>
  *
  * <table class="striped" style="margin-left:2em">
  *   <caption style="display:none">Description of unicast and multicast address types</caption>
@@ -105,7 +105,7 @@
  * </tbody>
  * </table>
  *
- * <h4> IP address scope </h4>
+ * <h3> IP address scope </h3>
  *
  * <p> <i>Link-local</i> addresses are designed to be used for addressing
  * on a single link for purposes such as auto-address configuration,
@@ -116,7 +116,7 @@
  *
  * <p> <i>Global</i> addresses are unique across the internet.
  *
- * <h4> Textual representation of IP addresses </h4>
+ * <h3> Textual representation of IP addresses </h3>
  *
  * The textual representation of an IP address is address family specific.
  *
@@ -130,7 +130,7 @@
  * <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of
  * System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P>
  *
- * <h4> Host Name Resolution </h4>
+ * <h3> Host Name Resolution </h3>
  *
  * Host name-to-IP address <i>resolution</i> is accomplished through
  * the use of a combination of local machine configuration information
@@ -145,7 +145,7 @@
  * <p> The InetAddress class provides methods to resolve host names to
  * their IP addresses and vice versa.
  *
- * <h4> InetAddress Caching </h4>
+ * <h3> InetAddress Caching </h3>
  *
  * The InetAddress class has a cache to store successful as well as
  * unsuccessful host name resolutions.
--- a/src/java.base/share/classes/java/net/MulticastSocket.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/MulticastSocket.java	Tue Mar 26 09:05:10 2019 -0400
@@ -52,8 +52,9 @@
  * InetAddress group = InetAddress.getByName("228.5.6.7");
  * MulticastSocket s = new MulticastSocket(6789);
  * s.joinGroup(group);
- * DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
- *                             group, 6789);
+ * byte[] msgBytes = msg.getBytes(StandardCharsets.UTF_8);
+ * DatagramPacket hi = new DatagramPacket(msgBytes, msgBytes.length,
+ *                                        group, 6789);
  * s.send(hi);
  * // get their responses!
  * byte[] buf = new byte[1000];
--- a/src/java.base/share/classes/java/net/NetPermission.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/NetPermission.java	Tue Mar 26 09:05:10 2019 -0400
@@ -43,7 +43,7 @@
  * signify a wildcard match. For example: "foo.*" and "*" signify a wildcard
  * match, while "*foo" and "a*b" do not.
  * <P>
- * The following table lists all the possible NetPermission target names,
+ * The following table lists the standard NetPermission target names,
  * and for each provides a description of what the permission allows
  * and a discussion of the risks of granting code the permission.
  *
@@ -158,6 +158,10 @@
    </tbody>
  * </table>
  *
+ * @implNote
+ * Implementations may define additional target names, but should use naming
+ * conventions such as reverse domain name notation to avoid name clashes.
+ *
  * @see java.security.BasicPermission
  * @see java.security.Permission
  * @see java.security.Permissions
--- a/src/java.base/share/classes/java/net/ServerSocket.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/ServerSocket.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,6 @@
 
 package java.net;
 
-import jdk.internal.access.JavaNetSocketAccess;
-import jdk.internal.access.SharedSecrets;
-
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.lang.reflect.Constructor;
@@ -38,6 +35,10 @@
 import java.util.Set;
 import java.util.Collections;
 
+import jdk.internal.access.JavaNetSocketAccess;
+import jdk.internal.access.SharedSecrets;
+import sun.net.PlatformSocketImpl;
+
 /**
  * This class implements server sockets. A server socket waits for
  * requests to come in over the network. It performs some operation
@@ -290,13 +291,12 @@
     }
 
     private void setImpl() {
+        SocketImplFactory factory = ServerSocket.factory;
         if (factory != null) {
             impl = factory.createSocketImpl();
             checkOldImpl();
         } else {
-            // No need to do a checkOldImpl() here, we know it's an up to date
-            // SocketImpl!
-            impl = new SocksSocketImpl();
+            impl = SocketImpl.createPlatformSocketImpl(true);
         }
         if (impl != null)
             impl.setServerSocket(this);
@@ -542,38 +542,134 @@
      * @spec JSR-51
      */
     protected final void implAccept(Socket s) throws IOException {
-        SocketImpl si = null;
-        try {
-            if (s.impl == null)
-              s.setImpl();
-            else {
-                s.impl.reset();
+        SocketImpl si = s.impl;
+
+        // Socket has no SocketImpl
+        if (si == null) {
+            si = implAccept();
+            s.setImpl(si);
+            s.postAccept();
+            return;
+        }
+
+        // Socket has a SOCKS or HTTP SocketImpl, need delegate
+        if (si instanceof DelegatingSocketImpl) {
+            si = ((DelegatingSocketImpl) si).delegate();
+            assert si instanceof PlatformSocketImpl;
+        }
+
+        // Accept connection with a platform or custom SocketImpl.
+        // For the platform SocketImpl case:
+        // - the connection is accepted with a new SocketImpl
+        // - the SO_TIMEOUT socket option is copied to the new SocketImpl
+        // - the Socket is connected to the new SocketImpl
+        // - the existing/old SocketImpl is closed
+        // For the custom SocketImpl case, the connection is accepted with the
+        // existing custom SocketImpl.
+        ensureCompatible(si);
+        if (impl instanceof PlatformSocketImpl) {
+            SocketImpl psi = platformImplAccept();
+            si.copyOptionsTo(psi);
+            s.setImpl(psi);
+            si.closeQuietly();
+        } else {
+            s.impl = null; // temporarily break connection to impl
+            try {
+                customImplAccept(si);
+            } finally {
+                s.impl = si;  // restore connection to impl
             }
-            si = s.impl;
-            s.impl = null;
-            si.address = new InetAddress();
-            si.fd = new FileDescriptor();
-            getImpl().accept(si);
-            SocketCleanable.register(si.fd);   // raw fd has been set
+        }
+        s.postAccept();
+    }
 
-            SecurityManager security = System.getSecurityManager();
-            if (security != null) {
-                security.checkAccept(si.getInetAddress().getHostAddress(),
-                                     si.getPort());
+    /**
+     * Accepts a connection with a new SocketImpl.
+     * @return the new SocketImpl
+     */
+    private SocketImpl implAccept() throws IOException {
+        if (impl instanceof PlatformSocketImpl) {
+            return platformImplAccept();
+        } else {
+            // custom server SocketImpl, client SocketImplFactory must be set
+            SocketImplFactory factory = Socket.socketImplFactory();
+            if (factory == null) {
+                throw new IOException("An instance of " + impl.getClass() +
+                    " cannot accept connection with 'null' SocketImpl:" +
+                    " client socket implementation factory not set");
             }
-        } catch (IOException e) {
-            if (si != null)
-                si.reset();
-            s.impl = si;
-            throw e;
-        } catch (SecurityException e) {
-            if (si != null)
-                si.reset();
-            s.impl = si;
+            SocketImpl si = factory.createSocketImpl();
+            customImplAccept(si);
+            return si;
+        }
+    }
+
+    /**
+     * Accepts a connection with a new platform SocketImpl.
+     * @return the new platform SocketImpl
+     */
+    private SocketImpl platformImplAccept() throws IOException {
+        assert impl instanceof PlatformSocketImpl;
+
+        // create a new platform SocketImpl and accept the connection
+        SocketImpl psi = SocketImpl.createPlatformSocketImpl(false);
+        implAccept(psi);
+        return psi;
+    }
+
+    /**
+     * Accepts a new connection with the given custom SocketImpl.
+     */
+    private void customImplAccept(SocketImpl si) throws IOException {
+        assert !(impl instanceof PlatformSocketImpl)
+                && !(si instanceof PlatformSocketImpl);
+
+        si.reset();
+        try {
+            // custom SocketImpl may expect fd/address objects to be created
+            si.fd = new FileDescriptor();
+            si.address = new InetAddress();
+            implAccept(si);
+        } catch (Exception e) {
+            si.reset();
             throw e;
         }
-        s.impl = si;
-        s.postAccept();
+    }
+
+    /**
+     * Accepts a new connection so that the given SocketImpl is connected to
+     * the peer. The SocketImpl and connection are closed if the connection is
+     * denied by the security manager.
+     * @throws IOException if an I/O error occurs
+     * @throws SecurityException if the security manager's checkAccept method fails
+     */
+    private void implAccept(SocketImpl si) throws IOException {
+        assert !(si instanceof DelegatingSocketImpl);
+
+        // accept a connection
+        impl.accept(si);
+
+        // check permission, close SocketImpl/connection if denied
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            try {
+                sm.checkAccept(si.getInetAddress().getHostAddress(), si.getPort());
+            } catch (SecurityException se) {
+                si.close();
+                throw se;
+            }
+        }
+    }
+
+    /**
+     * Throws IOException if the server SocketImpl and the given client
+     * SocketImpl are not both platform or custom SocketImpls.
+     */
+    private void ensureCompatible(SocketImpl si) throws IOException {
+        if ((impl instanceof PlatformSocketImpl) != (si instanceof PlatformSocketImpl)) {
+            throw new IOException("An instance of " + impl.getClass() +
+                " cannot accept a connection with an instance of " + si.getClass());
+        }
     }
 
     /**
@@ -778,7 +874,7 @@
     /**
      * The factory for all server sockets.
      */
-    private static SocketImplFactory factory = null;
+    private static volatile SocketImplFactory factory;
 
     /**
      * Sets the server socket implementation factory for the
--- a/src/java.base/share/classes/java/net/Socket.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/Socket.java	Tue Mar 26 09:05:10 2019 -0400
@@ -28,9 +28,10 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.nio.channels.SocketChannel;
 import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedAction;
 import java.util.Set;
 import java.util.Collections;
@@ -76,6 +77,22 @@
     private boolean oldImpl = false;
 
     /**
+     * Socket input/output streams
+     */
+    private volatile InputStream in;
+    private volatile OutputStream out;
+    private static final VarHandle IN, OUT;
+    static {
+        try {
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            IN = l.findVarHandle(Socket.class, "in", InputStream.class);
+            OUT = l.findVarHandle(Socket.class, "out", OutputStream.class);
+        } catch (Exception e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
      * Creates an unconnected socket, with the
      * system-default type of SocketImpl.
      *
@@ -137,16 +154,22 @@
                     security.checkConnect(epoint.getAddress().getHostAddress(),
                                   epoint.getPort());
             }
-            impl = type == Proxy.Type.SOCKS ? new SocksSocketImpl(p)
-                                            : new HttpConnectSocketImpl(p);
+
+            // create a SOCKS or HTTP SocketImpl that delegates to a platform SocketImpl
+            SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
+            impl = (type == Proxy.Type.SOCKS) ? new SocksSocketImpl(p, delegate)
+                                              : new HttpConnectSocketImpl(p, delegate);
             impl.setSocket(this);
         } else {
             if (p == Proxy.NO_PROXY) {
+                // create a platform or custom SocketImpl for the DIRECT case
+                SocketImplFactory factory = Socket.factory;
                 if (factory == null) {
-                    impl = new PlainSocketImpl();
-                    impl.setSocket(this);
-                } else
-                    setImpl();
+                    impl = SocketImpl.createPlatformSocketImpl(false);
+                } else {
+                    impl = factory.createSocketImpl();
+                }
+                impl.setSocket(this);
             } else
                 throw new IllegalArgumentException("Invalid Proxy");
         }
@@ -491,24 +514,29 @@
         });
     }
 
+    void setImpl(SocketImpl si) {
+         impl = si;
+         impl.setSocket(this);
+    }
+
     /**
      * Sets impl to the system-default type of SocketImpl.
      * @since 1.4
      */
     void setImpl() {
+        SocketImplFactory factory = Socket.factory;
         if (factory != null) {
             impl = factory.createSocketImpl();
             checkOldImpl();
         } else {
-            // No need to do a checkOldImpl() here, we know it's an up to date
-            // SocketImpl!
-            impl = new SocksSocketImpl();
+            // create a SOCKS SocketImpl that delegates to a platform SocketImpl
+            SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
+            impl = new SocksSocketImpl(delegate);
         }
         if (impl != null)
             impl.setSocket(this);
     }
 
-
     /**
      * Get the {@code SocketImpl} attached to this socket, creating
      * it if necessary.
@@ -907,18 +935,49 @@
             throw new SocketException("Socket is not connected");
         if (isInputShutdown())
             throw new SocketException("Socket input is shutdown");
-        InputStream is = null;
-        try {
-            is = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<>() {
-                    public InputStream run() throws IOException {
-                        return impl.getInputStream();
-                    }
-                });
-        } catch (java.security.PrivilegedActionException e) {
-            throw (IOException) e.getException();
+        InputStream in = this.in;
+        if (in == null) {
+            // wrap the input stream so that the close method closes this socket
+            in = new SocketInputStream(this, impl.getInputStream());
+            if (!IN.compareAndSet(this, null, in)) {
+                in = this.in;
+            }
         }
-        return is;
+        return in;
+    }
+
+    /**
+     * An InputStream that delegates read/available operations to an underlying
+     * input stream. The close method is overridden to close the Socket.
+     *
+     * This class is instrumented by Java Flight Recorder (JFR) to get socket
+     * I/O events.
+     */
+    private static class SocketInputStream extends InputStream {
+        private final Socket parent;
+        private final InputStream in;
+        SocketInputStream(Socket parent, InputStream in) {
+            this.parent = parent;
+            this.in = in;
+        }
+        @Override
+        public int read() throws IOException {
+            byte[] a = new byte[1];
+            int n = read(a, 0, 1);
+            return (n > 0) ? (a[0] & 0xff) : -1;
+        }
+        @Override
+        public int read(byte b[], int off, int len) throws IOException {
+            return in.read(b, off, len);
+        }
+        @Override
+        public int available() throws IOException {
+            return in.available();
+        }
+        @Override
+        public void close() throws IOException {
+            parent.close();
+        }
     }
 
     /**
@@ -946,18 +1005,44 @@
             throw new SocketException("Socket is not connected");
         if (isOutputShutdown())
             throw new SocketException("Socket output is shutdown");
-        OutputStream os = null;
-        try {
-            os = AccessController.doPrivileged(
-                new PrivilegedExceptionAction<>() {
-                    public OutputStream run() throws IOException {
-                        return impl.getOutputStream();
-                    }
-                });
-        } catch (java.security.PrivilegedActionException e) {
-            throw (IOException) e.getException();
+        OutputStream out = this.out;
+        if (out == null) {
+            // wrap the output stream so that the close method closes this socket
+            out = new SocketOutputStream(this, impl.getOutputStream());
+            if (!OUT.compareAndSet(this, null, out)) {
+                out = this.out;
+            }
         }
-        return os;
+        return out;
+    }
+
+    /**
+     * An OutputStream that delegates write operations to an underlying output
+     * stream. The close method is overridden to close the Socket.
+     *
+     * This class is instrumented by Java Flight Recorder (JFR) to get socket
+     * I/O events.
+     */
+    private static class SocketOutputStream extends OutputStream {
+        private final Socket parent;
+        private final OutputStream out;
+        SocketOutputStream(Socket parent, OutputStream out) {
+            this.parent = parent;
+            this.out = out;
+        }
+        @Override
+        public void write(int b) throws IOException {
+            byte[] a = new byte[] { (byte) b };
+            write(a, 0, 1);
+        }
+        @Override
+        public void write(byte b[], int off, int len) throws IOException {
+            out.write(b, off, len);
+        }
+        @Override
+        public void close() throws IOException {
+            parent.close();
+        }
     }
 
     /**
@@ -1644,7 +1729,11 @@
     /**
      * The factory for all client sockets.
      */
-    private static SocketImplFactory factory = null;
+    private static volatile SocketImplFactory factory;
+
+    static SocketImplFactory socketImplFactory() {
+        return factory;
+    }
 
     /**
      * Sets the client socket implementation factory for the
--- a/src/java.base/share/classes/java/net/SocketImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/SocketImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,8 @@
 import java.io.FileDescriptor;
 import java.util.Set;
 
+import sun.net.PlatformSocketImpl;
+
 /**
  * The abstract class {@code SocketImpl} is a common superclass
  * of all classes that actually implement sockets. It is used to
@@ -43,6 +45,15 @@
  * @since   1.0
  */
 public abstract class SocketImpl implements SocketOptions {
+
+    /**
+     * Creates an instance of platform's SocketImpl
+     */
+    @SuppressWarnings("unchecked")
+    static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
+        return (S) new PlainSocketImpl();
+    }
+
     /**
      * The actual Socket object.
      */
@@ -178,6 +189,15 @@
     protected abstract void close() throws IOException;
 
     /**
+     * Closes this socket, ignoring any IOException that is thrown by close.
+     */
+    void closeQuietly() {
+        try {
+            close();
+        } catch (IOException ignore) { }
+    }
+
+    /**
      * Places the input stream for this socket at "end of stream".
      * Any data sent to this socket is acknowledged and then
      * silently discarded.
@@ -306,7 +326,8 @@
             ",port=" + getPort() + ",localport=" + getLocalPort()  + "]";
     }
 
-    void reset() throws IOException {
+    void reset() {
+        fd = null;
         address = null;
         port = 0;
         localport = 0;
@@ -443,6 +464,19 @@
         }
     }
 
+    /**
+     * Attempts to copy socket options from this SocketImpl to a target SocketImpl.
+     * At this time, only the SO_TIMEOUT make sense to copy.
+     */
+    void copyOptionsTo(SocketImpl target) {
+        try {
+            Object timeout = getOption(SocketOptions.SO_TIMEOUT);
+            if (timeout instanceof Integer) {
+                target.setOption(SocketOptions.SO_TIMEOUT, timeout);
+            }
+        } catch (IOException ignore) { }
+    }
+
     private static final Set<SocketOption<?>> socketOptions;
 
     private static final Set<SocketOption<?>> serverSocketOptions;
--- a/src/java.base/share/classes/java/net/SocksSocketImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/SocksSocketImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  * questions.
  */
 package java.net;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -36,11 +37,9 @@
 
 /**
  * SOCKS (V4 & V5) TCP socket implementation (RFC 1928).
- * This is a subclass of PlainSocketImpl.
- * Note this class should <b>NOT</b> be public.
  */
 
-class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
+class SocksSocketImpl extends DelegatingSocketImpl implements SocksConsts {
     private String server = null;
     private int serverPort = DEFAULT_PORT;
     private InetSocketAddress external_address;
@@ -49,11 +48,12 @@
     private InputStream cmdIn = null;
     private OutputStream cmdOut = null;
 
-    SocksSocketImpl() {
-        // Nothing needed
+    SocksSocketImpl(SocketImpl delegate) {
+        super(delegate);
     }
 
-    SocksSocketImpl(Proxy proxy) {
+    SocksSocketImpl(Proxy proxy, SocketImpl delegate) {
+        super(delegate);
         SocketAddress a = proxy.address();
         if (a instanceof InetSocketAddress) {
             InetSocketAddress ad = (InetSocketAddress) a;
@@ -75,7 +75,7 @@
     private synchronized void privilegedConnect(final String host,
                                               final int port,
                                               final int timeout)
-         throws IOException
+        throws IOException
     {
         try {
             AccessController.doPrivileged(
@@ -94,7 +94,7 @@
 
     private void superConnectServer(String host, int port,
                                     int timeout) throws IOException {
-        super.connect(new InetSocketAddress(host, port), timeout);
+        delegate.connect(new InetSocketAddress(host, port), timeout);
     }
 
     private static int remainingMillis(long deadlineMillis) throws IOException {
@@ -111,16 +111,23 @@
     private int readSocksReply(InputStream in, byte[] data, long deadlineMillis) throws IOException {
         int len = data.length;
         int received = 0;
-        while (received < len) {
-            int count;
-            try {
-                count = ((SocketInputStream)in).read(data, received, len - received, remainingMillis(deadlineMillis));
-            } catch (SocketTimeoutException e) {
-                throw new SocketTimeoutException("Connect timed out");
+        int originalTimeout = (int) getOption(SocketOptions.SO_TIMEOUT);
+        try {
+            while (received < len) {
+                int count;
+                int remaining = remainingMillis(deadlineMillis);
+                setOption(SocketOptions.SO_TIMEOUT, remaining);
+                try {
+                    count = in.read(data, received, len - received);
+                } catch (SocketTimeoutException e) {
+                    throw new SocketTimeoutException("Connect timed out");
+                }
+                if (count < 0)
+                    throw new SocketException("Malformed reply from SOCKS server");
+                received += count;
             }
-            if (count < 0)
-                throw new SocketException("Malformed reply from SOCKS server");
-            received += count;
+        } finally {
+            setOption(SocketOptions.SO_TIMEOUT, originalTimeout);
         }
         return received;
     }
@@ -239,6 +246,27 @@
         }
     }
 
+    @Override
+    protected void connect(String host, int port) throws IOException {
+        connect(new InetSocketAddress(host, port), 0);
+    }
+
+    @Override
+    protected void connect(InetAddress address, int port) throws IOException {
+        connect(new InetSocketAddress(address, port), 0);
+    }
+
+    @Override
+    void setSocket(Socket soc) {
+        delegate.socket = soc;
+        super.setSocket(soc);
+    }
+
+    @Override
+    void setServerSocket(ServerSocket soc) {
+        throw new InternalError("should not get here");
+    }
+
     /**
      * Connects the Socks Socket to the specified endpoint. It will first
      * connect to the SOCKS proxy and negotiate the access. If the proxy
@@ -290,7 +318,7 @@
                 /*
                  * No default proxySelector --> direct connection
                  */
-                super.connect(epoint, remainingMillis(deadlineMillis));
+                delegate.connect(epoint, remainingMillis(deadlineMillis));
                 return;
             }
             URI uri;
@@ -313,13 +341,13 @@
             java.util.Iterator<Proxy> iProxy = null;
             iProxy = sel.select(uri).iterator();
             if (iProxy == null || !(iProxy.hasNext())) {
-                super.connect(epoint, remainingMillis(deadlineMillis));
+                delegate.connect(epoint, remainingMillis(deadlineMillis));
                 return;
             }
             while (iProxy.hasNext()) {
                 p = iProxy.next();
                 if (p == null || p.type() != Proxy.Type.SOCKS) {
-                    super.connect(epoint, remainingMillis(deadlineMillis));
+                    delegate.connect(epoint, remainingMillis(deadlineMillis));
                     return;
                 }
 
@@ -509,7 +537,15 @@
         external_address = epoint;
     }
 
+    @Override
+    protected void listen(int backlog) {
+        throw new InternalError("should not get here");
+    }
 
+    @Override
+    protected void accept(SocketImpl s) {
+        throw new InternalError("should not get here");
+    }
 
     /**
      * Returns the value of this socket's {@code address} field.
@@ -522,7 +558,7 @@
         if (external_address != null)
             return external_address.getAddress();
         else
-            return super.getInetAddress();
+            return delegate.getInetAddress();
     }
 
     /**
@@ -536,7 +572,7 @@
         if (external_address != null)
             return external_address.getPort();
         else
-            return super.getPort();
+            return delegate.getPort();
     }
 
     @Override
@@ -544,10 +580,15 @@
         if (cmdsock != null)
             cmdsock.close();
         cmdsock = null;
-        super.close();
+        delegate.close();
     }
 
     private String getUserName() {
         return StaticProperty.userName();
     }
+
+    @Override
+    void reset() {
+        throw new InternalError("should not get here");
+    }
 }
--- a/src/java.base/share/classes/java/net/URI.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/URI.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@
  * and relativizing URI instances.  Instances of this class are immutable.
  *
  *
- * <h3> URI syntax and components </h3>
+ * <h2> URI syntax and components </h2>
  *
  * At the highest level a URI reference (hereinafter simply "URI") in string
  * form has the syntax
@@ -168,7 +168,7 @@
  * will be defined and the user-information and port components may be defined.
  *
  *
- * <h4> Operations on URI instances </h4>
+ * <h3> Operations on URI instances </h3>
  *
  * The key operations supported by this class are those of
  * <i>normalization</i>, <i>resolution</i>, and <i>relativization</i>.
@@ -247,7 +247,7 @@
  * yields the relative URI {@code sample/a/index.html#28}.
  *
  *
- * <h4> Character categories </h4>
+ * <h3> Character categories </h3>
  *
  * RFC&nbsp;2396 specifies precisely which characters are permitted in the
  * various components of a URI reference.  The following categories, most of
@@ -298,7 +298,7 @@
  * characters.
  *
  *
- * <h4> Escaped octets, quotation, encoding, and decoding </h4>
+ * <h3> Escaped octets, quotation, encoding, and decoding </h3>
  *
  * RFC 2396 allows escaped octets to appear in the user-info, path, query, and
  * fragment components.  Escaping serves two purposes in URIs:
@@ -390,7 +390,7 @@
  * </ul>
  *
  *
- * <h4> Identities </h4>
+ * <h3> Identities </h3>
  *
  * For any URI <i>u</i>, it is always the case that
  *
@@ -426,7 +426,7 @@
  * authority.
  *
  *
- * <h4> URIs, URLs, and URNs </h4>
+ * <h3> URIs, URLs, and URNs </h3>
  *
  * A URI is a uniform resource <i>identifier</i> while a URL is a uniform
  * resource <i>locator</i>.  Hence every URL is a URI, abstractly speaking, but
--- a/src/java.base/share/classes/java/net/doc-files/net-properties.html	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/net/doc-files/net-properties.html	Tue Mar 26 09:05:10 2019 -0400
@@ -1,6 +1,6 @@
 <!DOCTYPE HTML>
 <!--
- Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -208,7 +208,7 @@
 	      username. With this method existing applications that use the
 	      authenticator class do not need to be modified, as long as users
 	      are made aware that this notation must be used.</P>
-	  <LI><P>If a domain name is not specified as in method 2) and these
+	  <LI><P>If a domain name is not specified as in method 2) and this
 	      property is defined, then its value will be used a the domain
 	      name.</P>
 	</OL>
--- a/src/java.base/share/classes/java/nio/Buffer.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/nio/Buffer.java	Tue Mar 26 09:05:10 2019 -0400
@@ -731,11 +731,6 @@
         mark = -1;
     }
 
-    static void checkBounds(int off, int len, int size) { // package-private
-        if ((off | len | (off + len) | (size - (off + len))) < 0)
-            throw new IndexOutOfBoundsException();
-    }
-
     static {
         // setup access to this package in SharedSecrets
         SharedSecrets.setJavaNioAccess(
--- a/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/nio/ByteBufferAs-X-Buffer.java.template	Tue Mar 26 09:05:10 2019 -0400
@@ -87,8 +87,7 @@
 
     @Override
     public $Type$Buffer slice(int index, int length) {
-        Objects.checkIndex(index, limit() + 1);
-        Objects.checkIndex(length, limit() - index + 1);
+        Objects.checkFromIndexSize(index, length, limit());
         return new ByteBufferAs$Type$Buffer$RW$$BO$(bb,
                                                     -1,
                                                     0,
@@ -207,8 +206,7 @@
 #if[char]
 
     public String toString(int start, int end) {
-        if ((end > limit()) || (start > end))
-            throw new IndexOutOfBoundsException();
+        Objects.checkFromToIndex(start, end, limit());
         try {
             int len = end - start;
             char[] ca = new char[len];
@@ -233,8 +231,7 @@
         pos = (pos <= lim ? pos : lim);
         int len = lim - pos;
 
-        if ((start < 0) || (end > len) || (start > end))
-            throw new IndexOutOfBoundsException();
+        Objects.checkFromToIndex(start, end, len);
         return new ByteBufferAsCharBuffer$RW$$BO$(bb,
                                                   -1,
                                                   pos + start,
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Mar 26 09:05:10 2019 -0400
@@ -220,8 +220,7 @@
 
     @Override
     public $Type$Buffer slice(int index, int length) {
-        Objects.checkIndex(index, limit() + 1);
-        Objects.checkIndex(length, limit() - index + 1);
+        Objects.checkFromIndexSize(index, length, limit());
         return new Direct$Type$Buffer$RW$$BO$(this,
                                               -1,
                                               0,
@@ -291,7 +290,7 @@
     public $Type$Buffer get($type$[] dst, int offset, int length) {
 #if[rw]
         if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
-            checkBounds(offset, length, dst.length);
+            Objects.checkFromIndexSize(offset, length, dst.length);
             int pos = position();
             int lim = limit();
             assert (pos <= lim);
@@ -440,7 +439,7 @@
     public $Type$Buffer put($type$[] src, int offset, int length) {
 #if[rw]
         if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_FROM_ARRAY_THRESHOLD) {
-            checkBounds(offset, length, src.length);
+            Objects.checkFromIndexSize(offset, length, src.length);
             int pos = position();
             int lim = limit();
             assert (pos <= lim);
@@ -546,8 +545,7 @@
 #if[char]
 
     public String toString(int start, int end) {
-        if ((end > limit()) || (start > end))
-            throw new IndexOutOfBoundsException();
+        Objects.checkFromToIndex(start, end, limit());
         try {
             int len = end - start;
             char[] ca = new char[len];
@@ -572,8 +570,7 @@
         pos = (pos <= lim ? pos : lim);
         int len = lim - pos;
 
-        if ((start < 0) || (end > len) || (start > end))
-            throw new IndexOutOfBoundsException();
+        Objects.checkFromToIndex(start, end, len);
         return new DirectCharBuffer$RW$$BO$(this,
                                             -1,
                                             pos + start,
--- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Tue Mar 26 09:05:10 2019 -0400
@@ -104,18 +104,18 @@
     }
 
     public $Type$Buffer slice() {
+        int rem = this.remaining();
         return new Heap$Type$Buffer$RW$(hb,
                                         -1,
                                         0,
-                                        this.remaining(),
-                                        this.remaining(),
+                                        rem,
+                                        rem,
                                         this.position() + offset);
     }
 
     @Override
     public $Type$Buffer slice(int index, int length) {
-        Objects.checkIndex(index, limit() + 1);
-        Objects.checkIndex(length, limit() - index + 1);
+        Objects.checkFromIndexSize(index, length, limit());
         return new Heap$Type$Buffer$RW$(hb,
                                         -1,
                                         0,
@@ -173,11 +173,12 @@
 #end[streamableType]
 
     public $Type$Buffer get($type$[] dst, int offset, int length) {
-        checkBounds(offset, length, dst.length);
-        if (length > remaining())
+        Objects.checkFromIndexSize(offset, length, dst.length);
+        int pos = position();
+        if (length > limit() - pos)
             throw new BufferUnderflowException();
-        System.arraycopy(hb, ix(position()), dst, offset, length);
-        position(position() + length);
+        System.arraycopy(hb, ix(pos), dst, offset, length);
+        position(pos + length);
         return this;
     }
 
@@ -218,11 +219,12 @@
 
     public $Type$Buffer put($type$[] src, int offset, int length) {
 #if[rw]
-        checkBounds(offset, length, src.length);
-        if (length > remaining())
+        Objects.checkFromIndexSize(offset, length, src.length);
+        int pos = position();
+        if (length > limit() - pos)
             throw new BufferOverflowException();
-        System.arraycopy(src, offset, hb, ix(position()), length);
-        position(position() + length);
+        System.arraycopy(src, offset, hb, ix(pos), length);
+        position(pos + length);
         return this;
 #else[rw]
         throw new ReadOnlyBufferException();
@@ -235,19 +237,22 @@
             if (src == this)
                 throw createSameBufferException();
             Heap$Type$Buffer sb = (Heap$Type$Buffer)src;
-            int n = sb.remaining();
-            if (n > remaining())
+            int pos = position();
+            int sbpos = sb.position();
+            int n = sb.limit() - sbpos;
+            if (n > limit() - pos)
                 throw new BufferOverflowException();
-            System.arraycopy(sb.hb, sb.ix(sb.position()),
-                             hb, ix(position()), n);
-            sb.position(sb.position() + n);
-            position(position() + n);
+            System.arraycopy(sb.hb, sb.ix(sbpos),
+                             hb, ix(pos), n);
+            sb.position(sbpos + n);
+            position(pos + n);
         } else if (src.isDirect()) {
             int n = src.remaining();
-            if (n > remaining())
+            int pos = position();
+            if (n > limit() - pos)
                 throw new BufferOverflowException();
-            src.get(hb, ix(position()), n);
-            position(position() + n);
+            src.get(hb, ix(pos), n);
+            position(pos + n);
         } else {
             super.put(src);
         }
@@ -272,7 +277,7 @@
 
     public $Type$Buffer put(String src, int start, int end) {
         int length = end - start;
-        checkBounds(start, length, src.length());
+        Objects.checkFromIndexSize(start, length, src.length());
         if (isReadOnly())
             throw new ReadOnlyBufferException();
         int pos = position();
@@ -289,8 +294,10 @@
 
     public $Type$Buffer compact() {
 #if[rw]
-        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
-        position(remaining());
+        int pos = position();
+        int rem = limit() - pos;
+        System.arraycopy(hb, ix(pos), hb, ix(0), rem);
+        position(rem);
         limit(capacity());
         discardMark();
         return this;
@@ -348,8 +355,9 @@
     }
 
     public CharBuffer asCharBuffer() {
-        int size = this.remaining() >> 1;
-        long addr = address + position();
+        int pos = position();
+        int size = (limit() - pos) >> 1;
+        long addr = address + pos;
         return (bigEndian
                 ? (CharBuffer)(new ByteBufferAsCharBuffer$RW$B(this,
                                                                -1,
@@ -399,8 +407,9 @@
     }
 
     public ShortBuffer asShortBuffer() {
-        int size = this.remaining() >> 1;
-        long addr = address + position();
+        int pos = position();
+        int size = (limit() - pos) >> 1;
+        long addr = address + pos;
         return (bigEndian
                 ? (ShortBuffer)(new ByteBufferAsShortBuffer$RW$B(this,
                                                                  -1,
@@ -450,8 +459,9 @@
     }
 
     public IntBuffer asIntBuffer() {
-        int size = this.remaining() >> 2;
-        long addr = address + position();
+        int pos = position();
+        int size = (limit() - pos) >> 2;
+        long addr = address + pos;
         return (bigEndian
                 ? (IntBuffer)(new ByteBufferAsIntBuffer$RW$B(this,
                                                              -1,
@@ -501,8 +511,9 @@
     }
 
     public LongBuffer asLongBuffer() {
-        int size = this.remaining() >> 3;
-        long addr = address + position();
+        int pos = position();
+        int size = (limit() - pos) >> 3;
+        long addr = address + pos;
         return (bigEndian
                 ? (LongBuffer)(new ByteBufferAsLongBuffer$RW$B(this,
                                                                -1,
@@ -556,8 +567,9 @@
     }
 
     public FloatBuffer asFloatBuffer() {
-        int size = this.remaining() >> 2;
-        long addr = address + position();
+        int pos = position();
+        int size = (limit() - pos) >> 2;
+        long addr = address + pos;
         return (bigEndian
                 ? (FloatBuffer)(new ByteBufferAsFloatBuffer$RW$B(this,
                                                                  -1,
@@ -611,8 +623,9 @@
     }
 
     public DoubleBuffer asDoubleBuffer() {
-        int size = this.remaining() >> 3;
-        long addr = address + position();
+        int pos = position();
+        int size = (limit() - pos) >> 3;
+        long addr = address + pos;
         return (bigEndian
                 ? (DoubleBuffer)(new ByteBufferAsDoubleBuffer$RW$B(this,
                                                                    -1,
@@ -646,11 +659,8 @@
     // --- Methods to support CharSequence ---
 
     public CharBuffer subSequence(int start, int end) {
-        if ((start < 0)
-            || (end > length())
-            || (start > end))
-            throw new IndexOutOfBoundsException();
         int pos = position();
+        Objects.checkFromToIndex(start, end, limit() - pos);
         return new HeapCharBuffer$RW$(hb,
                                       -1,
                                       pos + start,
--- a/src/java.base/share/classes/java/nio/StringCharBuffer.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/nio/StringCharBuffer.java	Tue Mar 26 09:05:10 2019 -0400
@@ -37,8 +37,7 @@
     StringCharBuffer(CharSequence s, int start, int end) { // package-private
         super(-1, start, end, s.length());
         int n = s.length();
-        if ((start < 0) || (start > n) || (end < start) || (end > n))
-            throw new IndexOutOfBoundsException();
+        Objects.checkFromToIndex(start, end, n);
         str = s;
         this.isReadOnly = true;
     }
@@ -54,8 +53,7 @@
 
     @Override
     public CharBuffer slice(int index, int length) {
-        Objects.checkIndex(index, limit() + 1);
-        Objects.checkIndex(length, limit() - index + 1);
+        Objects.checkFromIndexSize(index, length, limit());
         return new StringCharBuffer(str,
                                     -1,
                                     0,
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template	Tue Mar 26 09:05:10 2019 -0400
@@ -772,7 +772,7 @@
      *          parameters do not hold
      */
     public $Type$Buffer get($type$[] dst, int offset, int length) {
-        checkBounds(offset, length, dst.length);
+        Objects.checkFromIndexSize(offset, length, dst.length);
         if (length > remaining())
             throw new BufferUnderflowException();
         int end = offset + length;
@@ -996,7 +996,7 @@
      *          If this buffer is read-only
      */
     public $Type$Buffer put($type$[] src, int offset, int length) {
-        checkBounds(offset, length, src.length);
+        Objects.checkFromIndexSize(offset, length, src.length);
         if (length > remaining())
             throw new BufferOverflowException();
         int end = offset + length;
@@ -1176,7 +1176,7 @@
      *          If this buffer is read-only
      */
     public $Type$Buffer put(String src, int start, int end) {
-        checkBounds(start, end - start, src.length());
+        Objects.checkFromIndexSize(start, end - start, src.length());
         if (isReadOnly())
             throw new ReadOnlyBufferException();
         if (end - start > remaining())
--- a/src/java.base/share/classes/java/text/ChoiceFormat.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/ChoiceFormat.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -151,7 +151,7 @@
  * }</pre>
  * </blockquote>
  *
- * <h3><a id="synchronization">Synchronization</a></h3>
+ * <h2><a id="synchronization">Synchronization</a></h2>
  *
  * <p>
  * Choice formats are not synchronized.
--- a/src/java.base/share/classes/java/text/CompactNumberFormat.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/CompactNumberFormat.java	Tue Mar 26 09:05:10 2019 -0400
@@ -73,7 +73,7 @@
  * String result = fmt.format(1000);
  * </pre></blockquote>
  *
- * <h3><a id="compact_number_style">Style</a></h3>
+ * <h2><a id="compact_number_style">Style</a></h2>
  * <p>
  * A number can be formatted in the compact forms with two different
  * styles, {@link NumberFormat.Style#SHORT SHORT}
@@ -88,7 +88,7 @@
  * {@link NumberFormat.Style#LONG LONG} style instance in same locale
  * formats {@code 10000} as {@code "10 thousand"}.
  *
- * <h3><a id="compact_number_patterns">Compact Number Patterns</a></h3>
+ * <h2><a id="compact_number_patterns">Compact Number Patterns</a></h2>
  * <p>
  * The compact number patterns are represented in a series of patterns where each
  * pattern is used to format a range of numbers. An example of
@@ -151,7 +151,7 @@
  * unless noted otherwise, if they are to appear in the prefix or suffix
  * as literals. For example, 0\u0915'.'.
  *
- * <h3>Formatting</h3>
+ * <h2>Formatting</h2>
  * The default formatting behavior returns a formatted string with no fractional
  * digits, however users can use the {@link #setMinimumFractionDigits(int)}
  * method to include the fractional part.
@@ -165,14 +165,14 @@
  * {@link java.text.DecimalFormat DecimalFormat}
  * for the specified locale is used.
  *
- * <h3>Parsing</h3>
+ * <h2>Parsing</h2>
  * The default parsing behavior does not allow a grouping separator until
  * grouping used is set to {@code true} by using
  * {@link #setGroupingUsed(boolean)}. The parsing of the fractional part
  * depends on the {@link #isParseIntegerOnly()}. For example, if the
  * parse integer only is set to true, then the fractional part is skipped.
  *
- * <h3>Rounding</h3>
+ * <h2>Rounding</h2>
  * {@code CompactNumberFormat} provides rounding modes defined in
  * {@link java.math.RoundingMode} for formatting.  By default, it uses
  * {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
@@ -836,7 +836,8 @@
             if (ch == QUOTE) {
                 ch = pattern.charAt(index++);
                 if (ch == MINUS_SIGN) {
-                    ch = symbols.getMinusSign();
+                    sb.append(symbols.getMinusSignText());
+                    continue;
                 }
             }
             sb.append(ch);
@@ -859,11 +860,14 @@
             if (ch == QUOTE) {
                 ch = pattern.charAt(index++);
                 if (ch == MINUS_SIGN) {
-                    ch = symbols.getMinusSign();
+                    String minusText = symbols.getMinusSignText();
                     FieldPosition fp = new FieldPosition(NumberFormat.Field.SIGN);
                     fp.setBeginIndex(stringIndex);
-                    fp.setEndIndex(stringIndex + 1);
+                    fp.setEndIndex(stringIndex + minusText.length());
                     positions.add(fp);
+                    stringIndex += minusText.length();
+                    affix.append(minusText);
+                    continue;
                 }
             }
             stringIndex++;
--- a/src/java.base/share/classes/java/text/DateFormat.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/DateFormat.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,7 @@
  * on the screen.
  * </ul>
  *
- * <h3><a id="synchronization">Synchronization</a></h3>
+ * <h2><a id="synchronization">Synchronization</a></h2>
  *
  * <p>
  * Date formats are not synchronized.
--- a/src/java.base/share/classes/java/text/DecimalFormat.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/DecimalFormat.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,20 +54,20 @@
 import sun.util.locale.provider.ResourceBundleBasedAdapter;
 
 /**
- * <code>DecimalFormat</code> is a concrete subclass of
- * <code>NumberFormat</code> that formats decimal numbers. It has a variety of
+ * {@code DecimalFormat} is a concrete subclass of
+ * {@code NumberFormat} that formats decimal numbers. It has a variety of
  * features designed to make it possible to parse and format numbers in any
  * locale, including support for Western, Arabic, and Indic digits.  It also
  * supports different kinds of numbers, including integers (123), fixed-point
  * numbers (123.4), scientific notation (1.23E4), percentages (12%), and
  * currency amounts ($123).  All of these can be localized.
  *
- * <p>To obtain a <code>NumberFormat</code> for a specific locale, including the
- * default locale, call one of <code>NumberFormat</code>'s factory methods, such
- * as <code>getInstance()</code>.  In general, do not call the
- * <code>DecimalFormat</code> constructors directly, since the
- * <code>NumberFormat</code> factory methods may return subclasses other than
- * <code>DecimalFormat</code>. If you need to customize the format object, do
+ * <p>To obtain a {@code NumberFormat} for a specific locale, including the
+ * default locale, call one of {@code NumberFormat}'s factory methods, such
+ * as {@code getInstance()}.  In general, do not call the
+ * {@code DecimalFormat} constructors directly, since the
+ * {@code NumberFormat} factory methods may return subclasses other than
+ * {@code DecimalFormat}. If you need to customize the format object, do
  * something like this:
  *
  * <blockquote><pre>
@@ -77,16 +77,16 @@
  * }
  * </pre></blockquote>
  *
- * <p>A <code>DecimalFormat</code> comprises a <em>pattern</em> and a set of
+ * <p>A {@code DecimalFormat} comprises a <em>pattern</em> and a set of
  * <em>symbols</em>.  The pattern may be set directly using
- * <code>applyPattern()</code>, or indirectly using the API methods.  The
- * symbols are stored in a <code>DecimalFormatSymbols</code> object.  When using
- * the <code>NumberFormat</code> factory methods, the pattern and symbols are
- * read from localized <code>ResourceBundle</code>s.
+ * {@code applyPattern()}, or indirectly using the API methods.  The
+ * symbols are stored in a {@code DecimalFormatSymbols} object.  When using
+ * the {@code NumberFormat} factory methods, the pattern and symbols are
+ * read from localized {@code ResourceBundle}s.
  *
- * <h3>Patterns</h3>
+ * <h2>Patterns</h2>
  *
- * <code>DecimalFormat</code> patterns have the following syntax:
+ * {@code DecimalFormat} patterns have the following syntax:
  * <blockquote><pre>
  * <i>Pattern:</i>
  *         <i>PositivePattern</i>
@@ -123,26 +123,26 @@
  *         0 <i>MinimumExponent<sub>opt</sub></i>
  * </pre></blockquote>
  *
- * <p>A <code>DecimalFormat</code> pattern contains a positive and negative
- * subpattern, for example, <code>"#,##0.00;(#,##0.00)"</code>.  Each
+ * <p>A {@code DecimalFormat} pattern contains a positive and negative
+ * subpattern, for example, {@code "#,##0.00;(#,##0.00)"}.  Each
  * subpattern has a prefix, numeric part, and suffix. The negative subpattern
  * is optional; if absent, then the positive subpattern prefixed with the
- * localized minus sign (<code>'-'</code> in most locales) is used as the
- * negative subpattern. That is, <code>"0.00"</code> alone is equivalent to
- * <code>"0.00;-0.00"</code>.  If there is an explicit negative subpattern, it
+ * localized minus sign ({@code '-'} in most locales) is used as the
+ * negative subpattern. That is, {@code "0.00"} alone is equivalent to
+ * {@code "0.00;-0.00"}.  If there is an explicit negative subpattern, it
  * serves only to specify the negative prefix and suffix; the number of digits,
  * minimal digits, and other characteristics are all the same as the positive
- * pattern. That means that <code>"#,##0.0#;(#)"</code> produces precisely
- * the same behavior as <code>"#,##0.0#;(#,##0.0#)"</code>.
+ * pattern. That means that {@code "#,##0.0#;(#)"} produces precisely
+ * the same behavior as {@code "#,##0.0#;(#,##0.0#)"}.
  *
  * <p>The prefixes, suffixes, and various symbols used for infinity, digits,
  * thousands separators, decimal separators, etc. may be set to arbitrary
  * values, and they will appear properly during formatting.  However, care must
  * be taken that the symbols and strings do not conflict, or parsing will be
  * unreliable.  For example, either the positive and negative prefixes or the
- * suffixes must be distinct for <code>DecimalFormat.parse()</code> to be able
+ * suffixes must be distinct for {@code DecimalFormat.parse()} to be able
  * to distinguish positive from negative values.  (If they are identical, then
- * <code>DecimalFormat</code> will behave as if no negative subpattern was
+ * {@code DecimalFormat} will behave as if no negative subpattern was
  * specified.)  Another example is that the decimal separator and thousands
  * separator should be distinct characters, or parsing will be impossible.
  *
@@ -151,10 +151,10 @@
  * of digits between the grouping characters, such as 3 for 100,000,000 or 4 for
  * 1,0000,0000.  If you supply a pattern with multiple grouping characters, the
  * interval between the last one and the end of the integer is the one that is
- * used. So <code>"#,##,###,####"</code> == <code>"######,####"</code> ==
- * <code>"##,####,####"</code>.
+ * used. So {@code "#,##,###,####"} == {@code "######,####"} ==
+ * {@code "##,####,####"}.
  *
- * <h4><a id="special_pattern_character">Special Pattern Characters</a></h4>
+ * <h3><a id="special_pattern_character">Special Pattern Characters</a></h3>
  *
  * <p>Many characters in a pattern are taken literally; they are matched during
  * parsing and output unchanged during formatting.  Special characters, on the
@@ -164,7 +164,7 @@
  *
  * <p>The characters listed here are used in non-localized patterns.  Localized
  * patterns use the corresponding characters taken from this formatter's
- * <code>DecimalFormatSymbols</code> object instead, and these characters lose
+ * {@code DecimalFormatSymbols} object instead, and these characters lose
  * their special status.  Two exceptions are the currency sign and quote, which
  * are not localized.
  *
@@ -180,53 +180,53 @@
  * </thead>
  * <tbody>
  *     <tr style="vertical-align:top">
- *          <th scope="row"><code>0</code>
+ *          <th scope="row">{@code 0}
  *          <td>Number
  *          <td>Yes
  *          <td>Digit
  *     <tr style="vertical-align: top">
- *          <th scope="row"><code>#</code>
+ *          <th scope="row">{@code #}
  *          <td>Number
  *          <td>Yes
  *          <td>Digit, zero shows as absent
  *     <tr style="vertical-align:top">
- *          <th scope="row"><code>.</code>
+ *          <th scope="row">{@code .}
  *          <td>Number
  *          <td>Yes
  *          <td>Decimal separator or monetary decimal separator
  *     <tr style="vertical-align: top">
- *          <th scope="row"><code>-</code>
+ *          <th scope="row">{@code -}
  *          <td>Number
  *          <td>Yes
  *          <td>Minus sign
  *     <tr style="vertical-align:top">
- *          <th scope="row"><code>,</code>
+ *          <th scope="row">{@code ,}
  *          <td>Number
  *          <td>Yes
  *          <td>Grouping separator
  *     <tr style="vertical-align: top">
- *          <th scope="row"><code>E</code>
+ *          <th scope="row">{@code E}
  *          <td>Number
  *          <td>Yes
  *          <td>Separates mantissa and exponent in scientific notation.
  *              <em>Need not be quoted in prefix or suffix.</em>
  *     <tr style="vertical-align:top">
- *          <th scope="row"><code>;</code>
+ *          <th scope="row">{@code ;}
  *          <td>Subpattern boundary
  *          <td>Yes
  *          <td>Separates positive and negative subpatterns
  *     <tr style="vertical-align: top">
- *          <th scope="row"><code>%</code>
+ *          <th scope="row">{@code %}
  *          <td>Prefix or suffix
  *          <td>Yes
  *          <td>Multiply by 100 and show as percentage
  *     <tr style="vertical-align:top">
- *          <th scope="row"><code>&#92;u2030</code>
+ *          <th scope="row">{@code &#92;u2030}
  *          <td>Prefix or suffix
  *          <td>Yes
  *          <td>Multiply by 1000 and show as per mille value
  *     <tr style="vertical-align: top">
- *          <th scope="row"><code>&#164;</code> (<code>&#92;u00A4</code>)
+ *          <th scope="row">{@code &#164;} ({@code &#92;u00A4})
  *          <td>Prefix or suffix
  *          <td>No
  *          <td>Currency sign, replaced by currency symbol.  If
@@ -234,35 +234,35 @@
  *              If present in a pattern, the monetary decimal separator
  *              is used instead of the decimal separator.
  *     <tr style="vertical-align:top">
- *          <th scope="row"><code>'</code>
+ *          <th scope="row">{@code '}
  *          <td>Prefix or suffix
  *          <td>No
  *          <td>Used to quote special characters in a prefix or suffix,
- *              for example, <code>"'#'#"</code> formats 123 to
- *              <code>"#123"</code>.  To create a single quote
- *              itself, use two in a row: <code>"# o''clock"</code>.
+ *              for example, {@code "'#'#"} formats 123 to
+ *              {@code "#123"}.  To create a single quote
+ *              itself, use two in a row: {@code "# o''clock"}.
  * </tbody>
  * </table>
  * </blockquote>
  *
- * <h4>Scientific Notation</h4>
+ * <h3>Scientific Notation</h3>
  *
  * <p>Numbers in scientific notation are expressed as the product of a mantissa
  * and a power of ten, for example, 1234 can be expressed as 1.234 x 10^3.  The
  * mantissa is often in the range 1.0 &le; x {@literal <} 10.0, but it need not
  * be.
- * <code>DecimalFormat</code> can be instructed to format and parse scientific
+ * {@code DecimalFormat} can be instructed to format and parse scientific
  * notation <em>only via a pattern</em>; there is currently no factory method
  * that creates a scientific notation format.  In a pattern, the exponent
  * character immediately followed by one or more digit characters indicates
- * scientific notation.  Example: <code>"0.###E0"</code> formats the number
- * 1234 as <code>"1.234E3"</code>.
+ * scientific notation.  Example: {@code "0.###E0"} formats the number
+ * 1234 as {@code "1.234E3"}.
  *
  * <ul>
  * <li>The number of digit characters after the exponent character gives the
  * minimum exponent digit count.  There is no maximum.  Negative exponents are
  * formatted using the localized minus sign, <em>not</em> the prefix and suffix
- * from the pattern.  This allows patterns such as <code>"0.###E0 m/s"</code>.
+ * from the pattern.  This allows patterns such as {@code "0.###E0 m/s"}.
  *
  * <li>The minimum and maximum number of integer digits are interpreted
  * together:
@@ -273,62 +273,62 @@
  * number of integer digits, and the minimum number of integer digits to be
  * interpreted as 1.  The most common use of this is to generate
  * <em>engineering notation</em>, in which the exponent is a multiple of three,
- * e.g., <code>"##0.#####E0"</code>. Using this pattern, the number 12345
- * formats to <code>"12.345E3"</code>, and 123456 formats to
- * <code>"123.456E3"</code>.
+ * e.g., {@code "##0.#####E0"}. Using this pattern, the number 12345
+ * formats to {@code "12.345E3"}, and 123456 formats to
+ * {@code "123.456E3"}.
  *
  * <li>Otherwise, the minimum number of integer digits is achieved by adjusting the
- * exponent.  Example: 0.00123 formatted with <code>"00.###E0"</code> yields
- * <code>"12.3E-4"</code>.
+ * exponent.  Example: 0.00123 formatted with {@code "00.###E0"} yields
+ * {@code "12.3E-4"}.
  * </ul>
  *
  * <li>The number of significant digits in the mantissa is the sum of the
  * <em>minimum integer</em> and <em>maximum fraction</em> digits, and is
  * unaffected by the maximum integer digits.  For example, 12345 formatted with
- * <code>"##0.##E0"</code> is <code>"12.3E3"</code>. To show all digits, set
+ * {@code "##0.##E0"} is {@code "12.3E3"}. To show all digits, set
  * the significant digits count to zero.  The number of significant digits
  * does not affect parsing.
  *
  * <li>Exponential patterns may not contain grouping separators.
  * </ul>
  *
- * <h4>Rounding</h4>
+ * <h3>Rounding</h3>
  *
- * <code>DecimalFormat</code> provides rounding modes defined in
+ * {@code DecimalFormat} provides rounding modes defined in
  * {@link java.math.RoundingMode} for formatting.  By default, it uses
  * {@link java.math.RoundingMode#HALF_EVEN RoundingMode.HALF_EVEN}.
  *
- * <h4>Digits</h4>
+ * <h3>Digits</h3>
  *
- * For formatting, <code>DecimalFormat</code> uses the ten consecutive
+ * For formatting, {@code DecimalFormat} uses the ten consecutive
  * characters starting with the localized zero digit defined in the
- * <code>DecimalFormatSymbols</code> object as digits. For parsing, these
+ * {@code DecimalFormatSymbols} object as digits. For parsing, these
  * digits as well as all Unicode decimal digits, as defined by
  * {@link Character#digit Character.digit}, are recognized.
  *
  * <h4>Special Values</h4>
  *
- * <p><code>NaN</code> is formatted as a string, which typically has a single character
- * <code>&#92;uFFFD</code>.  This string is determined by the
- * <code>DecimalFormatSymbols</code> object.  This is the only value for which
+ * <p>{@code NaN} is formatted as a string, which typically has a single character
+ * {@code &#92;uFFFD}.  This string is determined by the
+ * {@code DecimalFormatSymbols} object.  This is the only value for which
  * the prefixes and suffixes are not used.
  *
  * <p>Infinity is formatted as a string, which typically has a single character
- * <code>&#92;u221E</code>, with the positive or negative prefixes and suffixes
+ * {@code &#92;u221E}, with the positive or negative prefixes and suffixes
  * applied.  The infinity string is determined by the
- * <code>DecimalFormatSymbols</code> object.
+ * {@code DecimalFormatSymbols} object.
  *
- * <p>Negative zero (<code>"-0"</code>) parses to
+ * <p>Negative zero ({@code "-0"}) parses to
  * <ul>
- * <li><code>BigDecimal(0)</code> if <code>isParseBigDecimal()</code> is
+ * <li>{@code BigDecimal(0)} if {@code isParseBigDecimal()} is
  * true,
- * <li><code>Long(0)</code> if <code>isParseBigDecimal()</code> is false
- *     and <code>isParseIntegerOnly()</code> is true,
- * <li><code>Double(-0.0)</code> if both <code>isParseBigDecimal()</code>
- * and <code>isParseIntegerOnly()</code> are false.
+ * <li>{@code Long(0)} if {@code isParseBigDecimal()} is false
+ *     and {@code isParseIntegerOnly()} is true,
+ * <li>{@code Double(-0.0)} if both {@code isParseBigDecimal()}
+ * and {@code isParseIntegerOnly()} are false.
  * </ul>
  *
- * <h4><a id="synchronization">Synchronization</a></h4>
+ * <h3><a id="synchronization">Synchronization</a></h3>
  *
  * <p>
  * Decimal formats are generally not synchronized.
@@ -336,7 +336,7 @@
  * If multiple threads access a format concurrently, it must be synchronized
  * externally.
  *
- * <h4>Example</h4>
+ * <h3>Example</h3>
  *
  * <blockquote><pre>{@code
  * <strong>// Print out a number using the localized number, integer, currency,
@@ -425,7 +425,7 @@
      * locale.
      *
      * @param pattern a non-localized pattern string.
-     * @exception NullPointerException if <code>pattern</code> is null
+     * @exception NullPointerException if {@code pattern} is null
      * @exception IllegalArgumentException if the given pattern is invalid.
      * @see java.text.NumberFormat#getInstance
      * @see java.text.NumberFormat#getNumberInstance
@@ -475,7 +475,7 @@
      * <p>
      * This implementation uses the maximum precision permitted.
      * @param number     the number to format
-     * @param toAppendTo the <code>StringBuffer</code> to which the formatted
+     * @param toAppendTo the {@code StringBuffer} to which the formatted
      *                   text is to be appended
      * @param pos        keeps track on the position of the field within the
      *                   returned string. For example, for formatting a number
@@ -485,11 +485,11 @@
      *                   and end index of {@code fieldPosition} will be set
      *                   to 0 and 9, respectively for the output string
      *                   {@code 1,234,567.89}.
-     * @return           the value passed in as <code>toAppendTo</code>
-     * @exception        IllegalArgumentException if <code>number</code> is
-     *                   null or not an instance of <code>Number</code>.
-     * @exception        NullPointerException if <code>toAppendTo</code> or
-     *                   <code>pos</code> is null
+     * @return           the value passed in as {@code toAppendTo}
+     * @exception        IllegalArgumentException if {@code number} is
+     *                   null or not an instance of {@code Number}.
+     * @exception        NullPointerException if {@code toAppendTo} or
+     *                   {@code pos} is null
      * @exception        ArithmeticException if rounding is needed with rounding
      *                   mode being set to RoundingMode.UNNECESSARY
      * @see              java.text.FieldPosition
@@ -914,13 +914,13 @@
     }
 
     /**
-     * Formats an Object producing an <code>AttributedCharacterIterator</code>.
-     * You can use the returned <code>AttributedCharacterIterator</code>
+     * Formats an Object producing an {@code AttributedCharacterIterator}.
+     * You can use the returned {@code AttributedCharacterIterator}
      * to build the resulting String, as well as to determine information
      * about the resulting String.
      * <p>
      * Each attribute key of the AttributedCharacterIterator will be of type
-     * <code>NumberFormat.Field</code>, with the attribute value being the
+     * {@code NumberFormat.Field}, with the attribute value being the
      * same as the attribute key.
      *
      * @exception NullPointerException if obj is null.
@@ -1916,7 +1916,7 @@
             if (negativeExponent) {
                 exponent = -exponent;
                 fieldStart = result.length();
-                result.append(symbols.getMinusSign());
+                result.append(symbols.getMinusSignText());
                 delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,
                         fieldStart, result.length(), result);
             }
@@ -2042,17 +2042,17 @@
     }
 
     /**
-     * Appends the String <code>string</code> to <code>result</code>.
-     * <code>delegate</code> is notified of all  the
-     * <code>FieldPosition</code>s in <code>positions</code>.
+     * Appends the String {@code string} to {@code result}.
+     * {@code delegate} is notified of all  the
+     * {@code FieldPosition}s in {@code positions}.
      * <p>
-     * If one of the <code>FieldPosition</code>s in <code>positions</code>
-     * identifies a <code>SIGN</code> attribute, it is mapped to
-     * <code>signAttribute</code>. This is used
-     * to map the <code>SIGN</code> attribute to the <code>EXPONENT</code>
+     * If one of the {@code FieldPosition}s in {@code positions}
+     * identifies a {@code SIGN} attribute, it is mapped to
+     * {@code signAttribute}. This is used
+     * to map the {@code SIGN} attribute to the {@code EXPONENT}
      * attribute as necessary.
      * <p>
-     * This is used by <code>subformat</code> to add the prefix/suffix.
+     * This is used by {@code subformat} to add the prefix/suffix.
      */
     private void append(StringBuffer result, String string,
                         FieldDelegate delegate,
@@ -2078,60 +2078,60 @@
     }
 
     /**
-     * Parses text from a string to produce a <code>Number</code>.
+     * Parses text from a string to produce a {@code Number}.
      * <p>
      * The method attempts to parse text starting at the index given by
-     * <code>pos</code>.
-     * If parsing succeeds, then the index of <code>pos</code> is updated
+     * {@code pos}.
+     * If parsing succeeds, then the index of {@code pos} is updated
      * to the index after the last character used (parsing does not necessarily
      * use all characters up to the end of the string), and the parsed
-     * number is returned. The updated <code>pos</code> can be used to
+     * number is returned. The updated {@code pos} can be used to
      * indicate the starting point for the next call to this method.
-     * If an error occurs, then the index of <code>pos</code> is not
-     * changed, the error index of <code>pos</code> is set to the index of
+     * If an error occurs, then the index of {@code pos} is not
+     * changed, the error index of {@code pos} is set to the index of
      * the character where the error occurred, and null is returned.
      * <p>
      * The subclass returned depends on the value of {@link #isParseBigDecimal}
      * as well as on the string being parsed.
      * <ul>
-     *   <li>If <code>isParseBigDecimal()</code> is false (the default),
-     *       most integer values are returned as <code>Long</code>
-     *       objects, no matter how they are written: <code>"17"</code> and
-     *       <code>"17.000"</code> both parse to <code>Long(17)</code>.
-     *       Values that cannot fit into a <code>Long</code> are returned as
-     *       <code>Double</code>s. This includes values with a fractional part,
-     *       infinite values, <code>NaN</code>, and the value -0.0.
-     *       <code>DecimalFormat</code> does <em>not</em> decide whether to
-     *       return a <code>Double</code> or a <code>Long</code> based on the
+     *   <li>If {@code isParseBigDecimal()} is false (the default),
+     *       most integer values are returned as {@code Long}
+     *       objects, no matter how they are written: {@code "17"} and
+     *       {@code "17.000"} both parse to {@code Long(17)}.
+     *       Values that cannot fit into a {@code Long} are returned as
+     *       {@code Double}s. This includes values with a fractional part,
+     *       infinite values, {@code NaN}, and the value -0.0.
+     *       {@code DecimalFormat} does <em>not</em> decide whether to
+     *       return a {@code Double} or a {@code Long} based on the
      *       presence of a decimal separator in the source string. Doing so
      *       would prevent integers that overflow the mantissa of a double,
-     *       such as <code>"-9,223,372,036,854,775,808.00"</code>, from being
+     *       such as {@code "-9,223,372,036,854,775,808.00"}, from being
      *       parsed accurately.
      *       <p>
-     *       Callers may use the <code>Number</code> methods
-     *       <code>doubleValue</code>, <code>longValue</code>, etc., to obtain
+     *       Callers may use the {@code Number} methods
+     *       {@code doubleValue}, {@code longValue}, etc., to obtain
      *       the type they want.
-     *   <li>If <code>isParseBigDecimal()</code> is true, values are returned
-     *       as <code>BigDecimal</code> objects. The values are the ones
+     *   <li>If {@code isParseBigDecimal()} is true, values are returned
+     *       as {@code BigDecimal} objects. The values are the ones
      *       constructed by {@link java.math.BigDecimal#BigDecimal(String)}
      *       for corresponding strings in locale-independent format. The
      *       special cases negative and positive infinity and NaN are returned
-     *       as <code>Double</code> instances holding the values of the
-     *       corresponding <code>Double</code> constants.
+     *       as {@code Double} instances holding the values of the
+     *       corresponding {@code Double} constants.
      * </ul>
      * <p>
-     * <code>DecimalFormat</code> parses all Unicode characters that represent
-     * decimal digits, as defined by <code>Character.digit()</code>. In
-     * addition, <code>DecimalFormat</code> also recognizes as digits the ten
+     * {@code DecimalFormat} parses all Unicode characters that represent
+     * decimal digits, as defined by {@code Character.digit()}. In
+     * addition, {@code DecimalFormat} also recognizes as digits the ten
      * consecutive characters starting with the localized zero digit defined in
-     * the <code>DecimalFormatSymbols</code> object.
+     * the {@code DecimalFormatSymbols} object.
      *
      * @param text the string to be parsed
-     * @param pos  A <code>ParsePosition</code> object with index and error
+     * @param pos  A {@code ParsePosition} object with index and error
      *             index information as described above.
-     * @return     the parsed value, or <code>null</code> if the parse fails
-     * @exception  NullPointerException if <code>text</code> or
-     *             <code>pos</code> is null.
+     * @return     the parsed value, or {@code null} if the parse fails
+     * @exception  NullPointerException if {@code text} or
+     *             {@code pos} is null.
      */
     @Override
     public Number parse(String text, ParsePosition pos) {
@@ -2475,7 +2475,7 @@
                     boolean[] stat = new boolean[STATUS_LENGTH];
                     DigitList exponentDigits = new DigitList();
 
-                    if (subparse(text, pos, "", Character.toString(symbols.getMinusSign()), exponentDigits, true, stat) &&
+                    if (subparse(text, pos, "", symbols.getMinusSignText(), exponentDigits, true, stat) &&
                             exponentDigits.fitsIntoLong(stat[STATUS_POSITIVE], true)) {
                         position = pos.index; // Advance past the exponent
                         exponent = (int)exponentDigits.getLong();
@@ -2573,7 +2573,7 @@
     /**
      * Returns the FieldPositions of the fields in the prefix used for
      * positive numbers. This is not used if the user has explicitly set
-     * a positive prefix via <code>setPositivePrefix</code>. This is
+     * a positive prefix via {@code setPositivePrefix}. This is
      * lazily created.
      *
      * @return FieldPositions in positive prefix
@@ -2614,7 +2614,7 @@
     /**
      * Returns the FieldPositions of the fields in the prefix used for
      * negative numbers. This is not used if the user has explicitly set
-     * a negative prefix via <code>setNegativePrefix</code>. This is
+     * a negative prefix via {@code setNegativePrefix}. This is
      * lazily created.
      *
      * @return FieldPositions in positive prefix
@@ -2655,7 +2655,7 @@
     /**
      * Returns the FieldPositions of the fields in the suffix used for
      * positive numbers. This is not used if the user has explicitly set
-     * a positive suffix via <code>setPositiveSuffix</code>. This is
+     * a positive suffix via {@code setPositiveSuffix}. This is
      * lazily created.
      *
      * @return FieldPositions in positive prefix
@@ -2696,7 +2696,7 @@
     /**
      * Returns the FieldPositions of the fields in the suffix used for
      * negative numbers. This is not used if the user has explicitly set
-     * a negative suffix via <code>setNegativeSuffix</code>. This is
+     * a negative suffix via {@code setNegativeSuffix}. This is
      * lazily created.
      *
      * @return FieldPositions in positive prefix
@@ -2811,7 +2811,7 @@
 
     /**
      * Returns whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
-     * method returns <code>BigDecimal</code>. The default value is false.
+     * method returns {@code BigDecimal}. The default value is false.
      *
      * @return {@code true} if the parse method returns BigDecimal;
      *         {@code false} otherwise
@@ -2824,7 +2824,7 @@
 
     /**
      * Sets whether the {@link #parse(java.lang.String, java.text.ParsePosition)}
-     * method returns <code>BigDecimal</code>.
+     * method returns {@code BigDecimal}.
      *
      * @param newValue {@code true} if the parse method returns BigDecimal;
      *                 {@code false} otherwise
@@ -2991,14 +2991,14 @@
                     }
                     continue;
                 case PATTERN_PERCENT:
-                    c = symbols.getPercent();
-                    break;
+                    buffer.append(symbols.getPercentText());
+                    continue;
                 case PATTERN_PER_MILLE:
-                    c = symbols.getPerMill();
-                    break;
+                    buffer.append(symbols.getPerMillText());
+                    continue;
                 case PATTERN_MINUS:
-                    c = symbols.getMinusSign();
-                    break;
+                    buffer.append(symbols.getMinusSignText());
+                    continue;
                 }
             }
             buffer.append(c);
@@ -3027,12 +3027,11 @@
         for (int i=0; i<pattern.length(); ) {
             char c = pattern.charAt(i++);
             if (c == QUOTE) {
-                int field = -1;
                 Format.Field fieldID = null;
+                String string = null;
                 c = pattern.charAt(i++);
                 switch (c) {
                 case CURRENCY_SIGN:
-                    String string;
                     if (i<pattern.length() &&
                         pattern.charAt(i) == CURRENCY_SIGN) {
                         ++i;
@@ -3040,41 +3039,32 @@
                     } else {
                         string = symbols.getCurrencySymbol();
                     }
-                    if (!string.isEmpty()) {
-                        if (positions == null) {
-                            positions = new ArrayList<>(2);
-                        }
-                        FieldPosition fp = new FieldPosition(Field.CURRENCY);
-                        fp.setBeginIndex(stringIndex);
-                        fp.setEndIndex(stringIndex + string.length());
-                        positions.add(fp);
-                        stringIndex += string.length();
-                    }
-                    continue;
+                    fieldID = Field.CURRENCY;
+                    break;
                 case PATTERN_PERCENT:
-                    c = symbols.getPercent();
-                    field = -1;
+                    string = symbols.getPercentText();
                     fieldID = Field.PERCENT;
                     break;
                 case PATTERN_PER_MILLE:
-                    c = symbols.getPerMill();
-                    field = -1;
+                    string = symbols.getPerMillText();
                     fieldID = Field.PERMILLE;
                     break;
                 case PATTERN_MINUS:
-                    c = symbols.getMinusSign();
-                    field = -1;
+                    string = symbols.getMinusSignText();
                     fieldID = Field.SIGN;
                     break;
                 }
-                if (fieldID != null) {
+
+                if (fieldID != null && !string.isEmpty()) {
                     if (positions == null) {
                         positions = new ArrayList<>(2);
                     }
-                    FieldPosition fp = new FieldPosition(fieldID, field);
+                    FieldPosition fp = new FieldPosition(fieldID);
                     fp.setBeginIndex(stringIndex);
-                    fp.setEndIndex(stringIndex + 1);
+                    fp.setEndIndex(stringIndex + string.length());
                     positions.add(fp);
+                    stringIndex += string.length();
+                    continue;
                 }
             }
             stringIndex++;
@@ -3129,14 +3119,14 @@
                 } else if (localized) {
                     switch (c) {
                     case PATTERN_PERCENT:
-                        c = symbols.getPercent();
-                        break;
+                        buffer.append(symbols.getPercentText());
+                        continue;
                     case PATTERN_PER_MILLE:
-                        c = symbols.getPerMill();
-                        break;
+                        buffer.append(symbols.getPerMillText());
+                        continue;
                     case PATTERN_MINUS:
-                        c = symbols.getMinusSign();
-                        break;
+                        buffer.append(symbols.getMinusSignText());
+                        continue;
                     }
                 }
                 buffer.append(c);
@@ -3155,11 +3145,11 @@
             needQuote = affix.indexOf(symbols.getZeroDigit()) >= 0
                 || affix.indexOf(symbols.getGroupingSeparator()) >= 0
                 || affix.indexOf(symbols.getDecimalSeparator()) >= 0
-                || affix.indexOf(symbols.getPercent()) >= 0
-                || affix.indexOf(symbols.getPerMill()) >= 0
+                || affix.indexOf(symbols.getPercentText()) >= 0
+                || affix.indexOf(symbols.getPerMillText()) >= 0
                 || affix.indexOf(symbols.getDigit()) >= 0
                 || affix.indexOf(symbols.getPatternSeparator()) >= 0
-                || affix.indexOf(symbols.getMinusSign()) >= 0
+                || affix.indexOf(symbols.getMinusSignText()) >= 0
                 || affix.indexOf(CURRENCY_SIGN) >= 0;
         } else {
             needQuote = affix.indexOf(PATTERN_ZERO_DIGIT) >= 0
@@ -3235,7 +3225,7 @@
                     if ((negPrefixPattern != null && posPrefixPattern != null &&
                          negPrefixPattern.equals("'-" + posPrefixPattern)) ||
                         (negPrefixPattern == posPrefixPattern && // n == p == null
-                         negativePrefix.equals(symbols.getMinusSign() + positivePrefix)))
+                         negativePrefix.equals(symbols.getMinusSignText() + positivePrefix)))
                         break;
                 }
                 result.append(localized ? symbols.getPatternSeparator() :
@@ -3255,16 +3245,16 @@
      * by this routine, since that is the typical end-user desire;
      * use setMaximumInteger if you want to set a real value.
      * For negative numbers, use a second pattern, separated by a semicolon
-     * <P>Example <code>"#,#00.0#"</code> &rarr; 1,234.56
+     * <P>Example {@code "#,#00.0#"} &rarr; 1,234.56
      * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
      * a maximum of 2 fraction digits.
-     * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
+     * <p>Example: {@code "#,#00.0#;(#,#00.0#)"} for negatives in
      * parentheses.
      * <p>In negative patterns, the minimum and maximum counts are ignored;
      * these are presumed to be set in the positive pattern.
      *
      * @param pattern a new pattern
-     * @exception NullPointerException if <code>pattern</code> is null
+     * @exception NullPointerException if {@code pattern} is null
      * @exception IllegalArgumentException if the given pattern is invalid.
      */
     public void applyPattern(String pattern) {
@@ -3282,16 +3272,16 @@
      * by this routine, since that is the typical end-user desire;
      * use setMaximumInteger if you want to set a real value.
      * For negative numbers, use a second pattern, separated by a semicolon
-     * <P>Example <code>"#,#00.0#"</code> &rarr; 1,234.56
+     * <P>Example {@code "#,#00.0#"} &rarr; 1,234.56
      * <P>This means a minimum of 2 integer digits, 1 fraction digit, and
      * a maximum of 2 fraction digits.
-     * <p>Example: <code>"#,#00.0#;(#,#00.0#)"</code> for negatives in
+     * <p>Example: {@code "#,#00.0#;(#,#00.0#)"} for negatives in
      * parentheses.
      * <p>In negative patterns, the minimum and maximum counts are ignored;
      * these are presumed to be set in the positive pattern.
      *
      * @param pattern a new pattern
-     * @exception NullPointerException if <code>pattern</code> is null
+     * @exception NullPointerException if {@code pattern} is null
      * @exception IllegalArgumentException if the given pattern is invalid.
      */
     public void applyLocalizedPattern(String pattern) {
@@ -3309,7 +3299,7 @@
         char perMill           = PATTERN_PER_MILLE;
         char digit             = PATTERN_DIGIT;
         char separator         = PATTERN_SEPARATOR;
-        String exponent          = PATTERN_EXPONENT;
+        String exponent        = PATTERN_EXPONENT;
         char minus             = PATTERN_MINUS;
         if (localized) {
             zeroDigit         = symbols.getZeroDigit();
@@ -3635,8 +3625,8 @@
     /**
      * Sets the maximum number of digits allowed in the integer portion of a
      * number.
-     * For formatting numbers other than <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
+     * For formatting numbers other than {@code BigInteger} and
+     * {@code BigDecimal} objects, the lower of {@code newValue} and
      * 309 is used. Negative input values are replaced with 0.
      * @see NumberFormat#setMaximumIntegerDigits
      */
@@ -3656,8 +3646,8 @@
     /**
      * Sets the minimum number of digits allowed in the integer portion of a
      * number.
-     * For formatting numbers other than <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
+     * For formatting numbers other than {@code BigInteger} and
+     * {@code BigDecimal} objects, the lower of {@code newValue} and
      * 309 is used. Negative input values are replaced with 0.
      * @see NumberFormat#setMinimumIntegerDigits
      */
@@ -3677,8 +3667,8 @@
     /**
      * Sets the maximum number of digits allowed in the fraction portion of a
      * number.
-     * For formatting numbers other than <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
+     * For formatting numbers other than {@code BigInteger} and
+     * {@code BigDecimal} objects, the lower of {@code newValue} and
      * 340 is used. Negative input values are replaced with 0.
      * @see NumberFormat#setMaximumFractionDigits
      */
@@ -3698,8 +3688,8 @@
     /**
      * Sets the minimum number of digits allowed in the fraction portion of a
      * number.
-     * For formatting numbers other than <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects, the lower of <code>newValue</code> and
+     * For formatting numbers other than {@code BigInteger} and
+     * {@code BigDecimal} objects, the lower of {@code newValue} and
      * 340 is used. Negative input values are replaced with 0.
      * @see NumberFormat#setMinimumFractionDigits
      */
@@ -3719,8 +3709,8 @@
     /**
      * Gets the maximum number of digits allowed in the integer portion of a
      * number.
-     * For formatting numbers other than <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects, the lower of the return value and
+     * For formatting numbers other than {@code BigInteger} and
+     * {@code BigDecimal} objects, the lower of the return value and
      * 309 is used.
      * @see #setMaximumIntegerDigits
      */
@@ -3732,8 +3722,8 @@
     /**
      * Gets the minimum number of digits allowed in the integer portion of a
      * number.
-     * For formatting numbers other than <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects, the lower of the return value and
+     * For formatting numbers other than {@code BigInteger} and
+     * {@code BigDecimal} objects, the lower of the return value and
      * 309 is used.
      * @see #setMinimumIntegerDigits
      */
@@ -3745,8 +3735,8 @@
     /**
      * Gets the maximum number of digits allowed in the fraction portion of a
      * number.
-     * For formatting numbers other than <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects, the lower of the return value and
+     * For formatting numbers other than {@code BigInteger} and
+     * {@code BigDecimal} objects, the lower of the return value and
      * 340 is used.
      * @see #setMaximumFractionDigits
      */
@@ -3758,8 +3748,8 @@
     /**
      * Gets the minimum number of digits allowed in the fraction portion of a
      * number.
-     * For formatting numbers other than <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects, the lower of the return value and
+     * For formatting numbers other than {@code BigInteger} and
+     * {@code BigDecimal} objects, the lower of the return value and
      * 340 is used.
      * @see #setMinimumFractionDigits
      */
@@ -3775,7 +3765,7 @@
      * {@link DecimalFormatSymbols#getCurrency DecimalFormatSymbols.getCurrency}
      * on this number format's symbols.
      *
-     * @return the currency used by this decimal format, or <code>null</code>
+     * @return the currency used by this decimal format, or {@code null}
      * @since 1.4
      */
     @Override
@@ -3792,7 +3782,7 @@
      * on this number format's symbols.
      *
      * @param currency the new currency to be used by this decimal format
-     * @exception NullPointerException if <code>currency</code> is null
+     * @exception NullPointerException if {@code currency} is null
      * @since 1.4
      */
     @Override
@@ -3809,7 +3799,7 @@
     /**
      * Gets the {@link java.math.RoundingMode} used in this DecimalFormat.
      *
-     * @return The <code>RoundingMode</code> used for this DecimalFormat.
+     * @return The {@code RoundingMode} used for this DecimalFormat.
      * @see #setRoundingMode(RoundingMode)
      * @since 1.6
      */
@@ -3821,9 +3811,9 @@
     /**
      * Sets the {@link java.math.RoundingMode} used in this DecimalFormat.
      *
-     * @param roundingMode The <code>RoundingMode</code> to be used
+     * @param roundingMode The {@code RoundingMode} to be used
      * @see #getRoundingMode()
-     * @exception NullPointerException if <code>roundingMode</code> is null.
+     * @exception NullPointerException if {@code roundingMode} is null.
      * @since 1.6
      */
     @Override
@@ -3845,38 +3835,38 @@
      * <li>
      * Verify that the superclass's digit count fields correctly reflect
      * the limits imposed on formatting numbers other than
-     * <code>BigInteger</code> and <code>BigDecimal</code> objects. These
+     * {@code BigInteger} and {@code BigDecimal} objects. These
      * limits are stored in the superclass for serialization compatibility
-     * with older versions, while the limits for <code>BigInteger</code> and
-     * <code>BigDecimal</code> objects are kept in this class.
+     * with older versions, while the limits for {@code BigInteger} and
+     * {@code BigDecimal} objects are kept in this class.
      * If, in the superclass, the minimum or maximum integer digit count is
-     * larger than <code>DOUBLE_INTEGER_DIGITS</code> or if the minimum or
+     * larger than {@code DOUBLE_INTEGER_DIGITS} or if the minimum or
      * maximum fraction digit count is larger than
-     * <code>DOUBLE_FRACTION_DIGITS</code>, then the stream data is invalid
-     * and this method throws an <code>InvalidObjectException</code>.
+     * {@code DOUBLE_FRACTION_DIGITS}, then the stream data is invalid
+     * and this method throws an {@code InvalidObjectException}.
      * <li>
-     * If <code>serialVersionOnStream</code> is less than 4, initialize
-     * <code>roundingMode</code> to {@link java.math.RoundingMode#HALF_EVEN
+     * If {@code serialVersionOnStream} is less than 4, initialize
+     * {@code roundingMode} to {@link java.math.RoundingMode#HALF_EVEN
      * RoundingMode.HALF_EVEN}.  This field is new with version 4.
      * <li>
-     * If <code>serialVersionOnStream</code> is less than 3, then call
+     * If {@code serialVersionOnStream} is less than 3, then call
      * the setters for the minimum and maximum integer and fraction digits with
      * the values of the corresponding superclass getters to initialize the
      * fields in this class. The fields in this class are new with version 3.
      * <li>
-     * If <code>serialVersionOnStream</code> is less than 1, indicating that
+     * If {@code serialVersionOnStream} is less than 1, indicating that
      * the stream was written by JDK 1.1, initialize
-     * <code>useExponentialNotation</code>
+     * {@code useExponentialNotation}
      * to false, since it was not present in JDK 1.1.
      * <li>
-     * Set <code>serialVersionOnStream</code> to the maximum allowed value so
+     * Set {@code serialVersionOnStream} to the maximum allowed value so
      * that default serialization will work properly if this object is streamed
      * out again.
      * </ol>
      *
      * <p>Stream versions older than 2 will not have the affix pattern variables
-     * <code>posPrefixPattern</code> etc.  As a result, they will be initialized
-     * to <code>null</code>, which means the affix strings will be taken as
+     * {@code posPrefixPattern} etc.  As a result, they will be initialized
+     * to {@code null}, which means the affix strings will be taken as
      * literal values.  This is exactly what we want, since that corresponds to
      * the pre-version-2 behavior.
      */
@@ -3960,14 +3950,14 @@
 
     /**
      * The prefix pattern for non-negative numbers.  This variable corresponds
-     * to <code>positivePrefix</code>.
+     * to {@code positivePrefix}.
      *
-     * <p>This pattern is expanded by the method <code>expandAffix()</code> to
-     * <code>positivePrefix</code> to update the latter to reflect changes in
-     * <code>symbols</code>.  If this variable is <code>null</code> then
-     * <code>positivePrefix</code> is taken as a literal value that does not
-     * change when <code>symbols</code> changes.  This variable is always
-     * <code>null</code> for <code>DecimalFormat</code> objects older than
+     * <p>This pattern is expanded by the method {@code expandAffix()} to
+     * {@code positivePrefix} to update the latter to reflect changes in
+     * {@code symbols}.  If this variable is {@code null} then
+     * {@code positivePrefix} is taken as a literal value that does not
+     * change when {@code symbols} changes.  This variable is always
+     * {@code null} for {@code DecimalFormat} objects older than
      * stream version 2 restored from stream.
      *
      * @serial
@@ -3977,8 +3967,8 @@
 
     /**
      * The suffix pattern for non-negative numbers.  This variable corresponds
-     * to <code>positiveSuffix</code>.  This variable is analogous to
-     * <code>posPrefixPattern</code>; see that variable for further
+     * to {@code positiveSuffix}.  This variable is analogous to
+     * {@code posPrefixPattern}; see that variable for further
      * documentation.
      *
      * @serial
@@ -3988,8 +3978,8 @@
 
     /**
      * The prefix pattern for negative numbers.  This variable corresponds
-     * to <code>negativePrefix</code>.  This variable is analogous to
-     * <code>posPrefixPattern</code>; see that variable for further
+     * to {@code negativePrefix}.  This variable is analogous to
+     * {@code posPrefixPattern}; see that variable for further
      * documentation.
      *
      * @serial
@@ -3999,8 +3989,8 @@
 
     /**
      * The suffix pattern for negative numbers.  This variable corresponds
-     * to <code>negativeSuffix</code>.  This variable is analogous to
-     * <code>posPrefixPattern</code>; see that variable for further
+     * to {@code negativeSuffix}.  This variable is analogous to
+     * {@code posPrefixPattern}; see that variable for further
      * documentation.
      *
      * @serial
@@ -4019,7 +4009,7 @@
     /**
      * The number of digits between grouping separators in the integer
      * portion of a number.  Must be greater than 0 if
-     * <code>NumberFormat.groupingUsed</code> is true.
+     * {@code NumberFormat.groupingUsed} is true.
      *
      * @serial
      * @see #getGroupingSize
@@ -4053,7 +4043,7 @@
     private transient boolean isCurrencyFormat = false;
 
     /**
-     * The <code>DecimalFormatSymbols</code> object used by this format.
+     * The {@code DecimalFormatSymbols} object used by this format.
      * It contains the symbols used to format numbers, e.g. the grouping separator,
      * decimal separator, and so on.
      *
@@ -4074,28 +4064,28 @@
 
     /**
      * FieldPositions describing the positive prefix String. This is
-     * lazily created. Use <code>getPositivePrefixFieldPositions</code>
+     * lazily created. Use {@code getPositivePrefixFieldPositions}
      * when needed.
      */
     private transient FieldPosition[] positivePrefixFieldPositions;
 
     /**
      * FieldPositions describing the positive suffix String. This is
-     * lazily created. Use <code>getPositiveSuffixFieldPositions</code>
+     * lazily created. Use {@code getPositiveSuffixFieldPositions}
      * when needed.
      */
     private transient FieldPosition[] positiveSuffixFieldPositions;
 
     /**
      * FieldPositions describing the negative prefix String. This is
-     * lazily created. Use <code>getNegativePrefixFieldPositions</code>
+     * lazily created. Use {@code getNegativePrefixFieldPositions}
      * when needed.
      */
     private transient FieldPosition[] negativePrefixFieldPositions;
 
     /**
      * FieldPositions describing the negative suffix String. This is
-     * lazily created. Use <code>getNegativeSuffixFieldPositions</code>
+     * lazily created. Use {@code getNegativeSuffixFieldPositions}
      * when needed.
      */
     private transient FieldPosition[] negativeSuffixFieldPositions;
@@ -4103,7 +4093,7 @@
     /**
      * The minimum number of digits used to display the exponent when a number is
      * formatted in exponential notation.  This field is ignored if
-     * <code>useExponentialNotation</code> is not true.
+     * {@code useExponentialNotation} is not true.
      *
      * @serial
      * @since 1.2
@@ -4112,9 +4102,9 @@
 
     /**
      * The maximum number of digits allowed in the integer portion of a
-     * <code>BigInteger</code> or <code>BigDecimal</code> number.
-     * <code>maximumIntegerDigits</code> must be greater than or equal to
-     * <code>minimumIntegerDigits</code>.
+     * {@code BigInteger} or {@code BigDecimal} number.
+     * {@code maximumIntegerDigits} must be greater than or equal to
+     * {@code minimumIntegerDigits}.
      *
      * @serial
      * @see #getMaximumIntegerDigits
@@ -4124,9 +4114,9 @@
 
     /**
      * The minimum number of digits allowed in the integer portion of a
-     * <code>BigInteger</code> or <code>BigDecimal</code> number.
-     * <code>minimumIntegerDigits</code> must be less than or equal to
-     * <code>maximumIntegerDigits</code>.
+     * {@code BigInteger} or {@code BigDecimal} number.
+     * {@code minimumIntegerDigits} must be less than or equal to
+     * {@code maximumIntegerDigits}.
      *
      * @serial
      * @see #getMinimumIntegerDigits
@@ -4136,9 +4126,9 @@
 
     /**
      * The maximum number of digits allowed in the fractional portion of a
-     * <code>BigInteger</code> or <code>BigDecimal</code> number.
-     * <code>maximumFractionDigits</code> must be greater than or equal to
-     * <code>minimumFractionDigits</code>.
+     * {@code BigInteger} or {@code BigDecimal} number.
+     * {@code maximumFractionDigits} must be greater than or equal to
+     * {@code minimumFractionDigits}.
      *
      * @serial
      * @see #getMaximumFractionDigits
@@ -4148,9 +4138,9 @@
 
     /**
      * The minimum number of digits allowed in the fractional portion of a
-     * <code>BigInteger</code> or <code>BigDecimal</code> number.
-     * <code>minimumFractionDigits</code> must be less than or equal to
-     * <code>maximumFractionDigits</code>.
+     * {@code BigInteger} or {@code BigDecimal} number.
+     * {@code minimumFractionDigits} must be less than or equal to
+     * {@code maximumFractionDigits}.
      *
      * @serial
      * @see #getMinimumFractionDigits
@@ -4247,19 +4237,19 @@
      * <ul>
      * <li><b>0</b> (default): versions before the Java 2 platform v1.2
      * <li><b>1</b>: version for 1.2, which includes the two new fields
-     *      <code>useExponentialNotation</code> and
-     *      <code>minExponentDigits</code>.
+     *      {@code useExponentialNotation} and
+     *      {@code minExponentDigits}.
      * <li><b>2</b>: version for 1.3 and later, which adds four new fields:
-     *      <code>posPrefixPattern</code>, <code>posSuffixPattern</code>,
-     *      <code>negPrefixPattern</code>, and <code>negSuffixPattern</code>.
+     *      {@code posPrefixPattern}, {@code posSuffixPattern},
+     *      {@code negPrefixPattern}, and {@code negSuffixPattern}.
      * <li><b>3</b>: version for 1.5 and later, which adds five new fields:
-     *      <code>maximumIntegerDigits</code>,
-     *      <code>minimumIntegerDigits</code>,
-     *      <code>maximumFractionDigits</code>,
-     *      <code>minimumFractionDigits</code>, and
-     *      <code>parseBigDecimal</code>.
+     *      {@code maximumIntegerDigits},
+     *      {@code minimumIntegerDigits},
+     *      {@code maximumFractionDigits},
+     *      {@code minimumFractionDigits}, and
+     *      {@code parseBigDecimal}.
      * <li><b>4</b>: version for 1.6 and later, which adds one new field:
-     *      <code>roundingMode</code>.
+     *      {@code roundingMode}.
      * </ul>
      * @since 1.2
      * @serial
--- a/src/java.base/share/classes/java/text/DecimalFormatSymbols.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/DecimalFormatSymbols.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,12 +38,14 @@
 
 package java.text;
 
+import java.io.InvalidObjectException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.text.spi.DecimalFormatSymbolsProvider;
 import java.util.Currency;
 import java.util.Locale;
+import java.util.Objects;
 import sun.util.locale.provider.CalendarDataUtility;
 import sun.util.locale.provider.LocaleProviderAdapter;
 import sun.util.locale.provider.LocaleServiceProviderPool;
@@ -51,11 +53,11 @@
 
 /**
  * This class represents the set of symbols (such as the decimal separator,
- * the grouping separator, and so on) needed by <code>DecimalFormat</code>
- * to format numbers. <code>DecimalFormat</code> creates for itself an instance of
- * <code>DecimalFormatSymbols</code> from its locale data.  If you need to change any
- * of these symbols, you can get the <code>DecimalFormatSymbols</code> object from
- * your <code>DecimalFormat</code> and modify it.
+ * the grouping separator, and so on) needed by {@code DecimalFormat}
+ * to format numbers. {@code DecimalFormat} creates for itself an instance of
+ * {@code DecimalFormatSymbols} from its locale data.  If you need to change any
+ * of these symbols, you can get the {@code DecimalFormatSymbols} object from
+ * your {@code DecimalFormat} and modify it.
  *
  * <p>If the locale contains "rg" (region override)
  * <a href="../util/Locale.html#def_locale_extension">Unicode extension</a>,
@@ -107,7 +109,7 @@
      * instead of the Latin numbering system.
      *
      * @param locale the desired locale
-     * @exception NullPointerException if <code>locale</code> is null
+     * @exception NullPointerException if {@code locale} is null
      */
     public DecimalFormatSymbols( Locale locale ) {
         initialize( locale );
@@ -115,16 +117,16 @@
 
     /**
      * Returns an array of all locales for which the
-     * <code>getInstance</code> methods of this class can return
+     * {@code getInstance} methods of this class can return
      * localized instances.
      * The returned array represents the union of locales supported by the Java
      * runtime and by installed
      * {@link java.text.spi.DecimalFormatSymbolsProvider DecimalFormatSymbolsProvider}
-     * implementations.  It must contain at least a <code>Locale</code>
+     * implementations.  It must contain at least a {@code Locale}
      * instance equal to {@link java.util.Locale#US Locale.US}.
      *
      * @return an array of locales for which localized
-     *         <code>DecimalFormatSymbols</code> instances are available.
+     *         {@code DecimalFormatSymbols} instances are available.
      * @since 1.6
      */
     public static Locale[] getAvailableLocales() {
@@ -134,8 +136,8 @@
     }
 
     /**
-     * Gets the <code>DecimalFormatSymbols</code> instance for the default
-     * locale.  This method provides access to <code>DecimalFormatSymbols</code>
+     * Gets the {@code DecimalFormatSymbols} instance for the default
+     * locale.  This method provides access to {@code DecimalFormatSymbols}
      * instances for locales supported by the Java runtime itself as well
      * as for those supported by installed
      * {@link java.text.spi.DecimalFormatSymbolsProvider
@@ -145,7 +147,7 @@
      *     getInstance(Locale.getDefault(Locale.Category.FORMAT))}.
      * @see java.util.Locale#getDefault(java.util.Locale.Category)
      * @see java.util.Locale.Category#FORMAT
-     * @return a <code>DecimalFormatSymbols</code> instance.
+     * @return a {@code DecimalFormatSymbols} instance.
      * @since 1.6
      */
     public static final DecimalFormatSymbols getInstance() {
@@ -153,8 +155,8 @@
     }
 
     /**
-     * Gets the <code>DecimalFormatSymbols</code> instance for the specified
-     * locale.  This method provides access to <code>DecimalFormatSymbols</code>
+     * Gets the {@code DecimalFormatSymbols} instance for the specified
+     * locale.  This method provides access to {@code DecimalFormatSymbols}
      * instances for locales supported by the Java runtime itself as well
      * as for those supported by installed
      * {@link java.text.spi.DecimalFormatSymbolsProvider
@@ -169,8 +171,8 @@
      * instead of the Latin numbering system.
      *
      * @param locale the desired locale.
-     * @return a <code>DecimalFormatSymbols</code> instance.
-     * @exception NullPointerException if <code>locale</code> is null
+     * @return a {@code DecimalFormatSymbols} instance.
+     * @exception NullPointerException if {@code locale} is null
      * @since 1.6
      */
     public static final DecimalFormatSymbols getInstance(Locale locale) {
@@ -255,6 +257,41 @@
      */
     public void setPerMill(char perMill) {
         this.perMill = perMill;
+        this.perMillText = Character.toString(perMill);
+    }
+
+    /**
+     * Gets the string used for per mille sign. Different for Arabic, etc.
+     *
+     * @return the string used for per mille sign
+     * @since 13
+     */
+    String getPerMillText() {
+        return perMillText;
+    }
+
+    /**
+     * Sets the string used for per mille sign. Different for Arabic, etc.
+     *
+     * Setting the {@code perMillText} affects the return value of
+     * {@link #getPerMill()}, in which the first non-format character of
+     * {@code perMillText} is returned.
+     *
+     * @param perMillText the string used for per mille sign
+     * @throws NullPointerException if {@code perMillText} is null
+     * @throws IllegalArgumentException if {@code perMillText} is an empty string
+     * @see #getPerMill()
+     * @see #getPerMillText()
+     * @since 13
+     */
+    void setPerMillText(String perMillText) {
+        Objects.requireNonNull(perMillText);
+        if (perMillText.isEmpty()) {
+            throw new IllegalArgumentException("Empty argument string");
+        }
+
+        this.perMillText = perMillText;
+        this.perMill = findNonFormatChar(perMillText, '\u2030');
     }
 
     /**
@@ -273,6 +310,41 @@
      */
     public void setPercent(char percent) {
         this.percent = percent;
+        this.percentText = Character.toString(percent);
+    }
+
+    /**
+     * Gets the string used for percent sign. Different for Arabic, etc.
+     *
+     * @return the string used for percent sign
+     * @since 13
+     */
+    String getPercentText() {
+        return percentText;
+    }
+
+    /**
+     * Sets the string used for percent sign. Different for Arabic, etc.
+     *
+     * Setting the {@code percentText} affects the return value of
+     * {@link #getPercent()}, in which the first non-format character of
+     * {@code percentText} is returned.
+     *
+     * @param percentText the string used for percent sign
+     * @throws NullPointerException if {@code percentText} is null
+     * @throws IllegalArgumentException if {@code percentText} is an empty string
+     * @see #getPercent()
+     * @see #getPercentText()
+     * @since 13
+     */
+    void setPercentText(String percentText) {
+        Objects.requireNonNull(percentText);
+        if (percentText.isEmpty()) {
+            throw new IllegalArgumentException("Empty argument string");
+        }
+
+        this.percentText = percentText;
+        this.percent = findNonFormatChar(percentText, '%');
     }
 
     /**
@@ -373,6 +445,46 @@
      */
     public void setMinusSign(char minusSign) {
         this.minusSign = minusSign;
+        this.minusSignText = Character.toString(minusSign);
+    }
+
+    /**
+     * Gets the string used to represent minus sign. If no explicit
+     * negative format is specified, one is formed by prefixing
+     * minusSignText to the positive format.
+     *
+     * @return the string representing minus sign
+     * @since 13
+     */
+    String getMinusSignText() {
+        return minusSignText;
+    }
+
+    /**
+     * Sets the string used to represent minus sign. If no explicit
+     * negative format is specified, one is formed by prefixing
+     * minusSignText to the positive format.
+     *
+     * Setting the {@code minusSignText} affects the return value of
+     * {@link #getMinusSign()}, in which the first non-format character of
+     * {@code minusSignText} is returned.
+     *
+     * @param minusSignText the character representing minus sign
+     * @throws NullPointerException if {@code minusSignText} is null
+     * @throws IllegalArgumentException if {@code minusSignText} is an
+     *  empty string
+     * @see #getMinusSign()
+     * @see #getMinusSignText()
+     * @since 13
+     */
+    void setMinusSignText(String minusSignText) {
+        Objects.requireNonNull(minusSignText);
+        if (minusSignText.isEmpty()) {
+            throw new IllegalArgumentException("Empty argument string");
+        }
+
+        this.minusSignText = minusSignText;
+        this.minusSign = findNonFormatChar(minusSignText, '-');
     }
 
     /**
@@ -464,7 +576,7 @@
      * symbol attribute to the currency's ISO 4217 currency code.
      *
      * @param currency the new currency to be used
-     * @exception NullPointerException if <code>currency</code> is null
+     * @exception NullPointerException if {@code currency} is null
      * @since 1.4
      * @see #setCurrencySymbol
      * @see #setInternationalCurrencySymbol
@@ -540,7 +652,7 @@
      * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
      *
      * @param exp the exponent separator string
-     * @exception NullPointerException if <code>exp</code> is null
+     * @exception NullPointerException if {@code exp} is null
      * @see #getExponentSeparator()
      * @since 1.6
      */
@@ -583,9 +695,12 @@
         groupingSeparator == other.groupingSeparator &&
         decimalSeparator == other.decimalSeparator &&
         percent == other.percent &&
+        percentText.equals(other.percentText) &&
         perMill == other.perMill &&
+        perMillText.equals(other.perMillText) &&
         digit == other.digit &&
         minusSign == other.minusSign &&
+        minusSignText.equals(other.minusSignText) &&
         patternSeparator == other.patternSeparator &&
         infinity.equals(other.infinity) &&
         NaN.equals(other.NaN) &&
@@ -631,13 +746,16 @@
         decimalSeparator = numberElements[0].charAt(0);
         groupingSeparator = numberElements[1].charAt(0);
         patternSeparator = numberElements[2].charAt(0);
-        percent = numberElements[3].charAt(0);
+        percentText = numberElements[3];
+        percent = findNonFormatChar(percentText, '%');
         zeroDigit = numberElements[4].charAt(0); //different for Arabic,etc.
         digit = numberElements[5].charAt(0);
-        minusSign = numberElements[6].charAt(0);
+        minusSignText = numberElements[6];
+        minusSign = findNonFormatChar(minusSignText, '-');
         exponential = numberElements[7].charAt(0);
         exponentialSeparator = numberElements[7]; //string representation new since 1.6
-        perMill = numberElements[8].charAt(0);
+        perMillText = numberElements[8];
+        perMill = findNonFormatChar(perMillText, '\u2030');
         infinity  = numberElements[9];
         NaN = numberElements[10];
 
@@ -652,6 +770,16 @@
     }
 
     /**
+     * Obtains non-format single character from String
+     */
+    private char findNonFormatChar(String src, char defChar) {
+        return (char)src.chars()
+            .filter(c -> Character.getType(c) != Character.FORMAT)
+            .findFirst()
+            .orElse(defChar);
+    }
+
+    /**
      * Lazy initialization for currency related fields
      */
     private void initializeCurrency(Locale locale) {
@@ -704,18 +832,24 @@
     /**
      * Reads the default serializable fields, provides default values for objects
      * in older serial versions, and initializes non-serializable fields.
-     * If <code>serialVersionOnStream</code>
-     * is less than 1, initializes <code>monetarySeparator</code> to be
-     * the same as <code>decimalSeparator</code> and <code>exponential</code>
+     * If {@code serialVersionOnStream}
+     * is less than 1, initializes {@code monetarySeparator} to be
+     * the same as {@code decimalSeparator} and {@code exponential}
      * to be 'E'.
-     * If <code>serialVersionOnStream</code> is less than 2,
-     * initializes <code>locale</code>to the root locale, and initializes
-     * If <code>serialVersionOnStream</code> is less than 3, it initializes
-     * <code>exponentialSeparator</code> using <code>exponential</code>.
-     * Sets <code>serialVersionOnStream</code> back to the maximum allowed value so that
+     * If {@code serialVersionOnStream} is less than 2,
+     * initializes {@code locale}to the root locale, and initializes
+     * If {@code serialVersionOnStream} is less than 3, it initializes
+     * {@code exponentialSeparator} using {@code exponential}.
+     * If {@code serialVersionOnStream} is less than 4, it initializes
+     * {@code perMillText}, {@code percentText}, and
+     * {@code minusSignText} using {@code perMill}, {@code percent}, and
+     * {@code minusSign} respectively.
+     * Sets {@code serialVersionOnStream} back to the maximum allowed value so that
      * default serialization will work properly if this object is streamed out again.
      * Initializes the currency from the intlCurrencySymbol field.
      *
+     * @throws InvalidObjectException if {@code char} and {@code String}
+     *      representations of either percent, per mille, and/or minus sign disagree.
      * @since  1.1.6
      */
     private void readObject(ObjectInputStream stream)
@@ -735,6 +869,23 @@
             // didn't have exponentialSeparator. Create one using exponential
             exponentialSeparator = Character.toString(exponential);
         }
+        if (serialVersionOnStream < 4) {
+            // didn't have perMillText, percentText, and minusSignText.
+            // Create one using corresponding char variations.
+            perMillText = Character.toString(perMill);
+            percentText = Character.toString(percent);
+            minusSignText = Character.toString(minusSign);
+        } else {
+            // Check whether char and text fields agree
+            if (findNonFormatChar(perMillText, '\uFFFF') != perMill ||
+                findNonFormatChar(percentText, '\uFFFF') != percent ||
+                findNonFormatChar(minusSignText, '\uFFFF') != minusSign) {
+                throw new InvalidObjectException(
+                    "'char' and 'String' representations of either percent, " +
+                    "per mille, and/or minus sign disagree.");
+            }
+        }
+
         serialVersionOnStream = currentSerialVersion;
 
         if (intlCurrencySymbol != null) {
@@ -862,8 +1013,8 @@
      * The string used to separate the mantissa from the exponent.
      * Examples: "x10^" for 1.23x10^4, "E" for 1.23E4.
      * <p>
-     * If both <code>exponential</code> and <code>exponentialSeparator</code>
-     * exist, this <code>exponentialSeparator</code> has the precedence.
+     * If both {@code exponential} and {@code exponentialSeparator}
+     * exist, this {@code exponentialSeparator} has the precedence.
      *
      * @serial
      * @since 1.6
@@ -878,6 +1029,39 @@
      */
     private Locale locale;
 
+    /**
+     * String representation of per mille sign, which may include
+     * formatting characters, such as BiDi control characters.
+     * The first non-format character of this string is the same as
+     * {@code perMill}.
+     *
+     * @serial
+     * @since 13
+     */
+    private  String perMillText;
+
+    /**
+     * String representation of percent sign, which may include
+     * formatting characters, such as BiDi control characters.
+     * The first non-format character of this string is the same as
+     * {@code percent}.
+     *
+     * @serial
+     * @since 13
+     */
+    private  String percentText;
+
+    /**
+     * String representation of minus sign, which may include
+     * formatting characters, such as BiDi control characters.
+     * The first non-format character of this string is the same as
+     * {@code minusSign}.
+     *
+     * @serial
+     * @since 13
+     */
+    private  String minusSignText;
+
     // currency; only the ISO code is serialized.
     private transient Currency currency;
     private transient volatile boolean currencyInitialized;
@@ -891,23 +1075,28 @@
     //     monetarySeparator and exponential.
     // - 2 for version from J2SE 1.4, which includes locale field.
     // - 3 for version from J2SE 1.6, which includes exponentialSeparator field.
-    private static final int currentSerialVersion = 3;
+    // - 4 for version from Java SE 13, which includes perMillText, percentText,
+    //      and minusSignText field.
+    private static final int currentSerialVersion = 4;
 
     /**
-     * Describes the version of <code>DecimalFormatSymbols</code> present on the stream.
+     * Describes the version of {@code DecimalFormatSymbols} present on the stream.
      * Possible values are:
      * <ul>
      * <li><b>0</b> (or uninitialized): versions prior to JDK 1.1.6.
      *
      * <li><b>1</b>: Versions written by JDK 1.1.6 or later, which include
-     *      two new fields: <code>monetarySeparator</code> and <code>exponential</code>.
+     *      two new fields: {@code monetarySeparator} and {@code exponential}.
      * <li><b>2</b>: Versions written by J2SE 1.4 or later, which include a
-     *      new <code>locale</code> field.
+     *      new {@code locale} field.
      * <li><b>3</b>: Versions written by J2SE 1.6 or later, which include a
-     *      new <code>exponentialSeparator</code> field.
+     *      new {@code exponentialSeparator} field.
+     * <li><b>4</b>: Versions written by Java SE 13 or later, which include
+     *      new {@code perMillText}, {@code percentText}, and
+     *      {@code minusSignText} field.
      * </ul>
-     * When streaming out a <code>DecimalFormatSymbols</code>, the most recent format
-     * (corresponding to the highest allowable <code>serialVersionOnStream</code>)
+     * When streaming out a {@code DecimalFormatSymbols}, the most recent format
+     * (corresponding to the highest allowable {@code serialVersionOnStream})
      * is always written.
      *
      * @serial
--- a/src/java.base/share/classes/java/text/Format.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/Format.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@
  * no separator in between, and in this case the <code>parseObject</code> could
  * not tell which digits belong to which number.
  *
- * <h3>Subclassing</h3>
+ * <h2>Subclassing</h2>
  *
  * <p>
  * The Java Platform provides three specialized subclasses of <code>Format</code>--
@@ -115,7 +115,7 @@
  * the field. For examples of these constants, see <code>ERA_FIELD</code> and its
  * friends in {@link DateFormat}.
  *
- * <h4><a id="synchronization">Synchronization</a></h4>
+ * <h3><a id="synchronization">Synchronization</a></h3>
  *
  * <p>
  * Formats are generally not synchronized.
--- a/src/java.base/share/classes/java/text/MessageFormat.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/MessageFormat.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,7 @@
  * behavior is defined by the pattern that you provide as well as the
  * subformats used for inserted arguments.
  *
- * <h3><a id="patterns">Patterns and Their Interpretation</a></h3>
+ * <h2><a id="patterns">Patterns and Their Interpretation</a></h2>
  *
  * <code>MessageFormat</code> uses patterns of the following form:
  * <blockquote><pre>
@@ -220,7 +220,7 @@
  * </tbody>
  * </table>
  *
- * <h4>Usage Information</h4>
+ * <h3>Usage Information</h3>
  *
  * <p>
  * Here are some examples of usage.
@@ -326,7 +326,7 @@
  * // result now equals {new String("z")}
  * </pre></blockquote>
  *
- * <h4><a id="synchronization">Synchronization</a></h4>
+ * <h3><a id="synchronization">Synchronization</a></h3>
  *
  * <p>
  * Message formats are not synchronized.
--- a/src/java.base/share/classes/java/text/NumberFormat.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/NumberFormat.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -175,7 +175,7 @@
  *      numbers: "(12)" for -12.
  * </ol>
  *
- * <h3><a id="synchronization">Synchronization</a></h3>
+ * <h2><a id="synchronization">Synchronization</a></h2>
  *
  * <p>
  * Number formats are generally not synchronized.
--- a/src/java.base/share/classes/java/text/SimpleDateFormat.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/text/SimpleDateFormat.java	Tue Mar 26 09:05:10 2019 -0400
@@ -74,7 +74,7 @@
  * For more information on using these methods, see
  * {@link DateFormat}.
  *
- * <h3>Date and Time Patterns</h3>
+ * <h2>Date and Time Patterns</h2>
  * <p>
  * Date and time formats are specified by <em>date and time pattern</em>
  * strings.
@@ -370,7 +370,7 @@
  * <code>SimpleDateFormat</code> does not deal with the localization of text
  * other than the pattern letters; that's up to the client of the class.
  *
- * <h4>Examples</h4>
+ * <h3>Examples</h3>
  *
  * The following examples show how date and time patterns are interpreted in
  * the U.S. locale. The given date and time are 2001-07-04 12:08:56 local time
@@ -421,7 +421,7 @@
  * </table>
  * </blockquote>
  *
- * <h4><a id="synchronization">Synchronization</a></h4>
+ * <h3><a id="synchronization">Synchronization</a></h3>
  *
  * <p>
  * Date formats are not synchronized.
--- a/src/java.base/share/classes/java/time/Instant.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/Instant.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,7 @@
  * For both the epoch-second and nanosecond parts, a larger value is always later on the time-line
  * than a smaller value.
  *
- * <h3>Time-scale</h3>
+ * <h2>Time-scale</h2>
  * <p>
  * The length of the solar day is the standard way that humans measure time.
  * This has traditionally been subdivided into 24 hours of 60 minutes of 60 seconds,
--- a/src/java.base/share/classes/java/time/ZoneId.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/ZoneId.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -111,7 +111,7 @@
  * Similarly, a comparison of two IDs only examines the ID, whereas
  * a comparison of two rules examines the entire data set.
  *
- * <h3>Time-zone IDs</h3>
+ * <h2>Time-zone IDs</h2>
  * The ID is unique within the system.
  * There are three types of ID.
  * <p>
@@ -147,7 +147,7 @@
  * The recommended format for region IDs from groups other than TZDB is 'group~region'.
  * Thus if IATA data were defined, Utrecht airport would be 'IATA~UTC'.
  *
- * <h3>Serialization</h3>
+ * <h2>Serialization</h2>
  * This class can be serialized and stores the string zone ID in the external form.
  * The {@code ZoneOffset} subclass uses a dedicated format that only stores the
  * offset from UTC/Greenwich.
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -99,7 +99,7 @@
  * The chronology defines how the calendar system operates and the meaning of
  * the standard fields.
  *
- * <h3>When to use this interface</h3>
+ * <h2>When to use this interface</h2>
  * The design of the API encourages the use of {@code LocalDate} rather than this
  * interface, even in the case where the application needs to deal with multiple
  * calendar systems.
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -121,7 +121,7 @@
  *                first, last);
  * </pre>
  *
- * <h3>Adding Calendars</h3>
+ * <h2>Adding Calendars</h2>
  * <p> The set of calendars is extensible by defining a subclass of {@link ChronoLocalDate}
  * to represent a date instance and an implementation of {@code Chronology}
  * to be the factory for the ChronoLocalDate subclass.
--- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -102,7 +102,7 @@
  * The chronology defines how the calendar system operates and the meaning of
  * the standard fields.
  *
- * <h3>When to use this interface</h3>
+ * <h2>When to use this interface</h2>
  * The design of the API encourages the use of {@code LocalDateTime} rather than this
  * interface, even in the case where the application needs to deal with multiple
  * calendar systems. The rationale for this is explored in detail in {@link ChronoLocalDate}.
--- a/src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,7 +103,7 @@
  * The chronology defines how the calendar system operates and the meaning of
  * the standard fields.
  *
- * <h3>When to use this interface</h3>
+ * <h2>When to use this interface</h2>
  * The design of the API encourages the use of {@code ZonedDateTime} rather than this
  * interface, even in the case where the application needs to deal with multiple
  * calendar systems. The rationale for this is explored in detail in {@link ChronoLocalDate}.
--- a/src/java.base/share/classes/java/time/chrono/Chronology.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/chrono/Chronology.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -133,7 +133,7 @@
  * <li> {@link #date(TemporalAccessor) date(TemporalAccessor)}
  * </ul>
  *
- * <h3 id="addcalendars">Adding New Calendars</h3>
+ * <h2 id="addcalendars">Adding New Calendars</h2>
  * The set of available chronologies can be extended by applications.
  * Adding a new calendar system requires the writing of an implementation of
  * {@code Chronology}, {@code ChronoLocalDate} and {@code Era}.
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -150,7 +150,7 @@
  * class for formatting. The {@link #toFormat()} method returns an
  * implementation of {@code java.text.Format}.
  *
- * <h3 id="predefined">Predefined Formatters</h3>
+ * <h2 id="predefined">Predefined Formatters</h2>
  * <table class="striped" style="text-align:left">
  * <caption>Predefined Formatters</caption>
  * <thead>
@@ -258,7 +258,7 @@
  * </tbody>
  * </table>
  *
- * <h3 id="patterns">Patterns for Formatting and Parsing</h3>
+ * <h2 id="patterns">Patterns for Formatting and Parsing</h2>
  * Patterns are based on a simple sequence of letters and symbols.
  * A pattern is used to create a Formatter using the
  * {@link #ofPattern(String)} and {@link #ofPattern(String, Locale)} methods.
@@ -434,7 +434,7 @@
  * that you want to output directly to ensure that future changes do not break
  * your application.
  *
- * <h3 id="resolving">Resolving</h3>
+ * <h2 id="resolving">Resolving</h2>
  * Parsing is implemented as a two-phase operation.
  * First, the text is parsed using the layout defined by the formatter, producing
  * a {@code Map} of field to value, a {@code ZoneId} and a {@code Chronology}.
--- a/src/java.base/share/classes/java/time/temporal/IsoFields.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/temporal/IsoFields.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
  * <p>
  * This class defines fields and units that are specific to the ISO calendar system.
  *
- * <h3>Quarter of year</h3>
+ * <h2>Quarter of year</h2>
  * The ISO-8601 standard is based on the standard civic 12 month year.
  * This is commonly divided into four quarters, often abbreviated as Q1, Q2, Q3 and Q4.
  * <p>
@@ -107,7 +107,7 @@
  * <li>{@link ChronoField#YEAR YEAR} - the standard ISO year
  * </ul>
  *
- * <h3>Week based years</h3>
+ * <h2>Week based years</h2>
  * The ISO-8601 standard was originally intended as a data interchange format,
  * defining a string format for dates and times. However, it also defines an
  * alternate way of expressing the date, based on the concept of week-based-year.
--- a/src/java.base/share/classes/java/time/temporal/JulianFields.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/temporal/JulianFields.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -115,7 +115,7 @@
      * the Julian Day value is validated against the range of valid values.
      * In {@linkplain ResolverStyle#LENIENT lenient mode} no validation occurs.
      *
-     * <h3>Astronomical and Scientific Notes</h3>
+     * <h4>Astronomical and Scientific Notes</h4>
      * The standard astronomical definition uses a fraction to indicate the time-of-day,
      * where each day is counted from midday to midday. For example,
      * a fraction of 0 represents midday, a fraction of 0.25
@@ -169,7 +169,7 @@
      * the Modified Julian Day value is validated against the range of valid values.
      * In {@linkplain ResolverStyle#LENIENT lenient mode} no validation occurs.
      *
-     * <h3>Astronomical and Scientific Notes</h3>
+     * <h4>Astronomical and Scientific Notes</h4>
      * <pre>
      *  | ISO date          | Modified Julian Day |      Decimal MJD |
      *  | 1970-01-01T00:00  |             40,587  |       40,587.0   |
--- a/src/java.base/share/classes/java/time/temporal/Temporal.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/temporal/Temporal.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -92,7 +92,7 @@
  * of this interface may be in calendar systems other than ISO.
  * See {@link java.time.chrono.ChronoLocalDate} for a fuller discussion of the issues.
  *
- * <h3>When to implement</h3>
+ * <h2>When to implement</h2>
  * <p>
  * A class should implement this interface if it meets three criteria:
  * <ul>
--- a/src/java.base/share/classes/java/time/temporal/WeekFields.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/temporal/WeekFields.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -120,7 +120,7 @@
  * </ul>
  * Together these two values allow a year or month to be divided into weeks.
  *
- * <h3>Week of Month</h3>
+ * <h2>Week of Month</h2>
  * One field is used: week-of-month.
  * The calculation ensures that weeks never overlap a month boundary.
  * The month is divided into periods where each period starts on the defined first day-of-week.
@@ -145,14 +145,14 @@
  * </tbody>
  * </table>
  *
- * <h3>Week of Year</h3>
+ * <h2>Week of Year</h2>
  * One field is used: week-of-year.
  * The calculation ensures that weeks never overlap a year boundary.
  * The year is divided into periods where each period starts on the defined first day-of-week.
  * The earliest period is referred to as week 0 if it has less than the minimal number of days
  * and week 1 if it has at least the minimal number of days.
  *
- * <h3>Week Based Year</h3>
+ * <h2>Week Based Year</h2>
  * Two fields are used for week-based-year, one for the
  * {@link #weekOfWeekBasedYear() week-of-week-based-year} and one for
  * {@link #weekBasedYear() week-based-year}.  In a week-based-year, each week
--- a/src/java.base/share/classes/java/util/Calendar.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/Calendar.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -97,7 +97,7 @@
  * concrete subclass, such as <code>ERA</code>.  See individual field
  * documentation and subclass documentation for details.
  *
- * <h3>Getting and Setting Calendar Field Values</h3>
+ * <h2>Getting and Setting Calendar Field Values</h2>
  *
  * <p>The calendar field values can be set by calling the <code>set</code>
  * methods. Any field values set in a <code>Calendar</code> will not be
@@ -106,7 +106,7 @@
  * <code>get</code>, <code>getTimeInMillis</code>, <code>getTime</code>,
  * <code>add</code> and <code>roll</code> involves such calculation.
  *
- * <h4>Leniency</h4>
+ * <h3>Leniency</h3>
  *
  * <p><code>Calendar</code> has two modes for interpreting the calendar
  * fields, <em>lenient</em> and <em>non-lenient</em>.  When a
@@ -125,7 +125,7 @@
  * calculating its time or calendar field values if any out-of-range field
  * value has been set.
  *
- * <h4><a id="first_week">First Week</a></h4>
+ * <h3><a id="first_week">First Week</a></h3>
  *
  * <code>Calendar</code> defines a locale-specific seven day week using two
  * parameters: the first day of the week and the minimal days in first week
@@ -150,7 +150,7 @@
  * designate the week before week 1 of a year as week <code><i>n</i></code> of
  * the previous year.
  *
- * <h4>Calendar Fields Resolution</h4>
+ * <h3>Calendar Fields Resolution</h3>
  *
  * When computing a date and time from the calendar fields, there
  * may be insufficient information for the computation (such as only
@@ -210,7 +210,7 @@
  * runtime. Use {@link DateFormat}
  * to format dates.
  *
- * <h4>Field Manipulation</h4>
+ * <h3>Field Manipulation</h3>
  *
  * The calendar fields can be changed using three methods:
  * <code>set()</code>, <code>add()</code>, and <code>roll()</code>.
--- a/src/java.base/share/classes/java/util/Formatter.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/Formatter.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,7 @@
  *   // -&gt; s == "Duke's Birthday: May 23, 1995"
  * </pre></blockquote>
  *
- * <h3><a id="org">Organization</a></h3>
+ * <h2><a id="org">Organization</a></h2>
  *
  * <p> This specification is divided into two sections.  The first section, <a
  * href="#summary">Summary</a>, covers the basic formatting concepts.  This
@@ -150,13 +150,13 @@
  * details.  It is intended for users who want more precise specification of
  * formatting behavior.
  *
- * <h3><a id="summary">Summary</a></h3>
+ * <h2><a id="summary">Summary</a></h2>
  *
  * <p> This section is intended to provide a brief overview of formatting
  * concepts.  For precise behavioral details, refer to the <a
  * href="#detail">Details</a> section.
  *
- * <h4><a id="syntax">Format String Syntax</a></h4>
+ * <h3><a id="syntax">Format String Syntax</a></h3>
  *
  * <p> Every method which produces formatted output requires a <i>format
  * string</i> and an <i>argument list</i>.  The format string is a {@link
@@ -236,7 +236,7 @@
  *
  * </ul>
  *
- * <h4> Conversions </h4>
+ * <h3> Conversions </h3>
  *
  * <p> Conversions are divided into the following categories:
  *
@@ -376,7 +376,7 @@
  * <p> Any characters not explicitly defined as conversions are illegal and are
  * reserved for future extensions.
  *
- * <h4><a id="dt">Date/Time Conversions</a></h4>
+ * <h3><a id="dt">Date/Time Conversions</a></h3>
  *
  * <p> The following date and time conversion suffix characters are defined for
  * the {@code 't'} and {@code 'T'} conversions.  The types are similar to but
@@ -550,7 +550,7 @@
  * <p> Any characters not explicitly defined as date/time conversion suffixes
  * are illegal and are reserved for future extensions.
  *
- * <h4> Flags </h4>
+ * <h3> Flags </h3>
  *
  * <p> The following table summarizes the supported flags.  <i>y</i> means the
  * flag is supported for the indicated argument types.
@@ -636,13 +636,13 @@
  * <p> Any characters not explicitly defined as flags are illegal and are
  * reserved for future extensions.
  *
- * <h4> Width </h4>
+ * <h3> Width </h3>
  *
  * <p> The width is the minimum number of characters to be written to the
  * output.  For the line separator conversion, width is not applicable; if it
  * is provided, an exception will be thrown.
  *
- * <h4> Precision </h4>
+ * <h3> Precision </h3>
  *
  * <p> For general argument types, the precision is the maximum number of
  * characters to be written to the output.
@@ -657,7 +657,7 @@
  * and line separator conversions, the precision is not applicable; if a
  * precision is provided, an exception will be thrown.
  *
- * <h4> Argument Index </h4>
+ * <h3> Argument Index </h3>
  *
  * <p> The argument index is a decimal integer indicating the position of the
  * argument in the argument list.  The first argument is referenced by
@@ -676,7 +676,7 @@
  * </pre></blockquote>
  *
  * <hr>
- * <h3><a id="detail">Details</a></h3>
+ * <h2><a id="detail">Details</a></h2>
  *
  * <p> This section is intended to provide behavioral details for formatting,
  * including conditions and exceptions, supported data types, localization, and
@@ -717,7 +717,7 @@
  * invocation, then the {@link java.util.Locale.Category#FORMAT default locale}
  * is used.
  *
- * <h4><a id="dgen">General</a></h4>
+ * <h3><a id="dgen">General</a></h3>
  *
  * <p> The following general conversions may be applied to any argument type:
  *
@@ -814,7 +814,7 @@
  * the precision.  If the precision is not specified then there is no explicit
  * limit on the number of characters.
  *
- * <h4><a id="dchar">Character</a></h4>
+ * <h3><a id="dchar">Character</a></h3>
  *
  * This conversion may be applied to {@code char} and {@link Character}.  It
  * may also be applied to the types {@code byte}, {@link Byte},
@@ -853,7 +853,7 @@
  * <p> The precision is not applicable.  If the precision is specified then an
  * {@link IllegalFormatPrecisionException} will be thrown.
  *
- * <h4><a id="dnum">Numeric</a></h4>
+ * <h3><a id="dnum">Numeric</a></h3>
  *
  * <p> Numeric conversions are divided into the following categories:
  *
@@ -1547,7 +1547,7 @@
  * href="#floatDPrec">precision</a> is the same as defined for Float and
  * Double.
  *
- * <h4><a id="ddt">Date/Time</a></h4>
+ * <h3><a id="ddt">Date/Time</a></h3>
  *
  * <p> This conversion may be applied to {@code long}, {@link Long}, {@link
  * Calendar}, {@link Date} and {@link TemporalAccessor TemporalAccessor}
@@ -1796,7 +1796,7 @@
  * <p> The precision is not applicable.  If the precision is specified then an
  * {@link IllegalFormatPrecisionException} will be thrown.
  *
- * <h4><a id="dper">Percent</a></h4>
+ * <h3><a id="dper">Percent</a></h3>
  *
  * <p> The conversion does not correspond to any argument.
  *
@@ -1824,7 +1824,7 @@
  * </tbody>
  * </table>
  *
- * <h4><a id="dls">Line Separator</a></h4>
+ * <h3><a id="dls">Line Separator</a></h3>
  *
  * <p> The conversion does not correspond to any argument.
  *
@@ -1843,7 +1843,7 @@
  * {@link IllegalFormatFlagsException}, {@link IllegalFormatWidthException},
  * and {@link IllegalFormatPrecisionException}, respectively will be thrown.
  *
- * <h4><a id="dpos">Argument Index</a></h4>
+ * <h3><a id="dpos">Argument Index</a></h3>
  *
  * <p> Format specifiers can reference arguments in three ways:
  *
--- a/src/java.base/share/classes/java/util/GregorianCalendar.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/GregorianCalendar.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@
  * adjustment may be made if desired for dates that are prior to the Gregorian
  * changeover and which fall between January 1 and March 24.
  *
- * <h3><a id="week_and_year">Week Of Year and Week Year</a></h3>
+ * <h2><a id="week_and_year">Week Of Year and Week Year</a></h2>
  *
  * <p>Values calculated for the {@link Calendar#WEEK_OF_YEAR
  * WEEK_OF_YEAR} field range from 1 to 53. The first week of a
@@ -133,7 +133,7 @@
  * ends on January 10, 1998; the first three days of 1998 then are
  * part of week 53 of 1997 and their week year is 1997.
  *
- * <h4>Week Of Month</h4>
+ * <h3>Week Of Month</h3>
  *
  * <p>Values calculated for the <code>WEEK_OF_MONTH</code> field range from 0
  * to 6.  Week 1 of a month (the days with <code>WEEK_OF_MONTH =
@@ -153,7 +153,7 @@
  * <code>getMinimalDaysInFirstWeek()</code> is changed to 3, then January 1
  * through January 3 have a <code>WEEK_OF_MONTH</code> of 1.
  *
- * <h4>Default Fields Values</h4>
+ * <h3>Default Fields Values</h3>
  *
  * <p>The <code>clear</code> method sets calendar field(s)
  * undefined. <code>GregorianCalendar</code> uses the following
--- a/src/java.base/share/classes/java/util/Locale.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/Locale.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -190,7 +190,7 @@
  * requirement (is well-formed), but does not validate the value
  * itself.  See {@link Builder} for details.
  *
- * <h3><a id="def_locale_extension">Unicode locale/language extension</a></h3>
+ * <h2><a id="def_locale_extension">Unicode locale/language extension</a></h2>
  *
  * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
  * attributes and keywords to override or refine the default behavior
@@ -230,17 +230,17 @@
  * implementations in a Java Runtime Environment might not support any
  * particular Unicode locale attributes or key/type pairs.
  *
- * <h4>Creating a Locale</h4>
+ * <h3>Creating a Locale</h3>
  *
  * <p>There are several different ways to create a <code>Locale</code>
  * object.
  *
- * <h5>Builder</h5>
+ * <h4>Builder</h4>
  *
  * <p>Using {@link Builder} you can construct a <code>Locale</code> object
  * that conforms to BCP 47 syntax.
  *
- * <h5>Constructors</h5>
+ * <h4>Constructors</h4>
  *
  * <p>The <code>Locale</code> class provides three constructors:
  * <blockquote>
@@ -254,12 +254,12 @@
  * with language, country and variant, but you cannot specify
  * script or extensions.
  *
- * <h5>Factory Methods</h5>
+ * <h4>Factory Methods</h4>
  *
  * <p>The method {@link #forLanguageTag} creates a <code>Locale</code>
  * object for a well-formed BCP 47 language tag.
  *
- * <h5>Locale Constants</h5>
+ * <h4>Locale Constants</h4>
  *
  * <p>The <code>Locale</code> class provides a number of convenient constants
  * that you can use to create <code>Locale</code> objects for commonly used
@@ -271,7 +271,7 @@
  * </pre>
  * </blockquote>
  *
- * <h4><a id="LocaleMatching">Locale Matching</a></h4>
+ * <h3><a id="LocaleMatching">Locale Matching</a></h3>
  *
  * <p>If an application or a system is internationalized and provides localized
  * resources for multiple locales, it sometimes needs to find one or more
@@ -292,7 +292,7 @@
  * language ranges: basic and extended. See
  * {@link Locale.LanguageRange Locale.LanguageRange} for details.
  *
- * <h5>Filtering</h5>
+ * <h4>Filtering</h4>
  *
  * <p>The filtering operation returns all matching language tags. It is defined
  * in RFC 4647 as follows:
@@ -310,7 +310,7 @@
  * {@link Locale.FilteringMode} is a parameter to specify how filtering should
  * be done.
  *
- * <h5>Lookup</h5>
+ * <h4>Lookup</h4>
  *
  * <p>The lookup operation returns the best matching language tags. It is
  * defined in RFC 4647 as follows:
@@ -342,7 +342,7 @@
  * an {@link Iterator} over a {@link Collection} of language tags is treated as
  * the best matching one.
  *
- * <h4>Use of Locale</h4>
+ * <h3>Use of Locale</h3>
  *
  * <p>Once you've created a <code>Locale</code> you can query it for information
  * about itself. Use <code>getCountry</code> to get the country (or region)
@@ -385,7 +385,7 @@
  * <STRONG>just</STRONG> a mechanism for identifying objects,
  * <STRONG>not</STRONG> a container for the objects themselves.
  *
- * <h4>Compatibility</h4>
+ * <h3>Compatibility</h3>
  *
  * <p>In order to maintain compatibility with existing usage, Locale's
  * constructors retain their behavior prior to the Java Runtime
@@ -410,7 +410,7 @@
  * Clients desiring a string representation of the complete locale can
  * then always rely on <code>toLanguageTag</code> for this purpose.
  *
- * <h5><a id="special_cases_constructor">Special cases</a></h5>
+ * <h4><a id="special_cases_constructor">Special cases</a></h4>
  *
  * <p>For compatibility reasons, two
  * non-conforming locales are treated as special cases.  These are
@@ -435,7 +435,7 @@
  * constructor is called with the arguments "th", "TH", "TH", the
  * extension "u-nu-thai" is automatically added.
  *
- * <h5>Serialization</h5>
+ * <h4>Serialization</h4>
  *
  * <p>During serialization, writeObject writes all fields to the output
  * stream, including extensions.
@@ -444,7 +444,7 @@
  * in <a href="#special_cases_constructor">Special Cases</a>, only
  * for the two cases th_TH_TH and ja_JP_JP.
  *
- * <h5>Legacy language codes</h5>
+ * <h4>Legacy language codes</h4>
  *
  * <p>Locale's constructor has always converted three language codes to
  * their earlier, obsoleted forms: {@code he} maps to {@code iw},
@@ -462,7 +462,7 @@
  * lookup mechanism also implements this mapping, so that resources
  * can be named using either convention, see {@link ResourceBundle.Control}.
  *
- * <h5>Three-letter language/country(region) codes</h5>
+ * <h4>Three-letter language/country(region) codes</h4>
  *
  * <p>The Locale constructors have always specified that the language
  * and the country param be two characters in length, although in
--- a/src/java.base/share/classes/java/util/ResourceBundle.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/ResourceBundle.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -204,18 +204,18 @@
  * known concrete subclasses {@code ListResourceBundle} and
  * {@code PropertyResourceBundle} are thread-safe.
  *
- * <h3><a id="resource-bundle-modules">Resource Bundles and Named Modules</a></h3>
+ * <h2><a id="resource-bundle-modules">Resource Bundles and Named Modules</a></h2>
  *
  * Resource bundles can be deployed in modules in the following ways:
  *
- * <h4>Resource bundles together with an application</h4>
+ * <h3>Resource bundles together with an application</h3>
  *
  * Resource bundles can be deployed together with an application in the same
  * module.  In that case, the resource bundles are loaded
  * by code in the module by calling the {@link #getBundle(String)}
  * or {@link #getBundle(String, Locale)} method.
  *
- * <h4><a id="service-providers">Resource bundles as service providers</a></h4>
+ * <h3><a id="service-providers">Resource bundles as service providers</a></h3>
  *
  * Resource bundles can be deployed in one or more <em>service provider modules</em>
  * and they can be located using {@link ServiceLoader}.
@@ -232,7 +232,7 @@
  * provide resource bundles in any format such XML which replaces the need
  * of {@link Control ResourceBundle.Control}.
  *
- * <h4><a id="other-modules">Resource bundles in other modules and class path</a></h4>
+ * <h3><a id="other-modules">Resource bundles in other modules and class path</a></h3>
  *
  * Resource bundles in a named module may be <em>encapsulated</em> so that
  * it cannot be located by code in other modules.  Resource bundles
@@ -255,7 +255,7 @@
  * resource bundle provider</a>, it does not fall back to the
  * class loader search.
  *
- * <h4>Resource bundles in automatic modules</h4>
+ * <h3>Resource bundles in automatic modules</h3>
  *
  * A common format of resource bundles is in {@linkplain PropertyResourceBundle
  * .properties} file format.  Typically {@code .properties} resource bundles
@@ -300,7 +300,7 @@
  * the first one returned from {@link ServiceLoader} will be used.
  * A custom {@link Control} implementation is ignored by named modules.
  *
- * <h3>Cache Management</h3>
+ * <h2>Cache Management</h2>
  *
  * Resource bundle instances created by the <code>getBundle</code> factory
  * methods are cached by default, and the factory methods return the same
@@ -316,7 +316,7 @@
  * Control#needsReload(String, Locale, String, ClassLoader, ResourceBundle,
  * long) ResourceBundle.Control.needsReload} for details.
  *
- * <h3>Example</h3>
+ * <h2>Example</h2>
  *
  * The following is a very simple example of a <code>ResourceBundle</code>
  * subclass, <code>MyResources</code>, that manages two resources (for a larger number of
--- a/src/java.base/share/classes/java/util/Scanner.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/Scanner.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -155,7 +155,7 @@
  * {@link #reset} method will reset the value of the scanner's radix to
  * {@code 10} regardless of whether it was previously changed.
  *
- * <h3> <a id="localized-numbers">Localized numbers</a> </h3>
+ * <h2> <a id="localized-numbers">Localized numbers</a> </h2>
  *
  * <p> An instance of this class is capable of scanning numbers in the standard
  * formats as well as in the formats of the scanner's locale. A scanner's
@@ -216,7 +216,7 @@
  *         getInfinity()}
  * </dl></blockquote>
  *
- * <h4> <a id="number-syntax">Number syntax</a> </h4>
+ * <h3> <a id="number-syntax">Number syntax</a> </h3>
  *
  * <p> The strings that can be parsed as numbers by an instance of this class
  * are specified in terms of the following regular-expression grammar, where
--- a/src/java.base/share/classes/java/util/ServiceLoader.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/ServiceLoader.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@
  * service providers (based on the functionality they expose through the service),
  * and handling the possibility that no service providers are located.
  *
- * <h3> Obtaining a service loader </h3>
+ * <h2> Obtaining a service loader </h2>
  *
  * <p> An application obtains a service loader for a given service by invoking
  * one of the static {@code load} methods of {@code ServiceLoader}. If the
@@ -141,7 +141,7 @@
  *   <li> {@code get()} yields an instance of {@code CodecFactory} </li>
  * </ol>
  *
- * <h3> Designing services </h3>
+ * <h2> Designing services </h2>
  *
  * <p> A service is a single type, usually an interface or abstract class. A
  * concrete class can be used, but this is not recommended. The type may have
@@ -167,7 +167,7 @@
  *   or complicated to produce certain codecs. </p></li>
  * </ol>
  *
- * <h3> <a id="developing-service-providers">Developing service providers</a> </h3>
+ * <h2> <a id="developing-service-providers">Developing service providers</a> </h2>
  *
  * <p> A service provider is a single type, usually a concrete class. An
  * interface or abstract class is permitted because it may declare a static
@@ -188,7 +188,7 @@
  * the service loader's stream, without knowledge of the service providers'
  * locations.
  *
- * <h3> Deploying service providers as modules </h3>
+ * <h2> Deploying service providers as modules </h2>
  *
  * <p> A service provider that is developed in a module must be specified in a
  * <i>provides</i> directive in the module declaration. The provides directive
@@ -253,7 +253,7 @@
  * the service provider) will be instantiated by an entity (that is, a service
  * loader) which is outside the class's package.
  *
- * <h3> Deploying service providers on the class path </h3>
+ * <h2> Deploying service providers on the class path </h2>
  *
  * A service provider that is packaged as a JAR file for the class path is
  * identified by placing a <i>provider-configuration file</i> in the resource
@@ -293,7 +293,7 @@
  * not necessarily the class loader which ultimately locates the
  * provider-configuration file.
  *
- * <h3> Timing of provider discovery </h3>
+ * <h2> Timing of provider discovery </h2>
  *
  * <p> Service providers are loaded and instantiated lazily, that is, on demand.
  * A service loader maintains a cache of the providers that have been loaded so
@@ -306,7 +306,7 @@
  * locates any remaining providers. Caches are cleared via the {@link #reload
  * reload} method.
  *
- * <h3> <a id="errors">Errors</a> </h3>
+ * <h2> <a id="errors">Errors</a> </h2>
  *
  * <p> When using the service loader's {@code iterator}, the {@link
  * Iterator#hasNext() hasNext} and {@link Iterator#next() next} methods will
@@ -361,7 +361,7 @@
  *
  * </ul>
  *
- * <h3> Security </h3>
+ * <h2> Security </h2>
  *
  * <p> Service loaders always execute in the security context of the caller
  * of the iterator or stream methods and may also be restricted by the security
@@ -370,7 +370,7 @@
  * the methods of the iterators which they return, from within a privileged
  * security context.
  *
- * <h3> Concurrency </h3>
+ * <h2> Concurrency </h2>
  *
  * <p> Instances of this class are not safe for use by multiple concurrent
  * threads.
--- a/src/java.base/share/classes/java/util/TimeZone.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/TimeZone.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -114,7 +114,7 @@
  * </pre></blockquote>
  * For example, TimeZone.getTimeZone("GMT-8").getID() returns "GMT-08:00".
  *
- * <h3>Three-letter time zone IDs</h3>
+ * <h2>Three-letter time zone IDs</h2>
  *
  * For compatibility with JDK 1.1.x, some other three-letter time zone IDs
  * (such as "PST", "CTT", "AST") are also supported. However, <strong>their
--- a/src/java.base/share/classes/java/util/doc-files/coll-designfaq.html	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/doc-files/coll-designfaq.html	Tue Mar 26 09:05:10 2019 -0400
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <!--
- Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -29,14 +29,14 @@
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
 </head>
 <body>
-<h2>Java Collections API Design FAQ</h2>
+<h1>Java Collections API Design FAQ</h1>
 <!-- Body text begins here -->
 <hr>
 This document answers frequently asked questions concerning the
 design of the Java collections framework. It is derived from the
 large volume of traffic on the collections-comments alias. It
 serves as a design rationale for the collections framework.
-<h3>Core Interfaces - General Questions</h3>
+<h2>Core Interfaces - General Questions</h2>
 <ol>
 <li><a href="#a1"><b>Why don't you support immutability directly in
 the core collection interfaces so that you can do away with
@@ -50,7 +50,7 @@
 <li><a href="#a28"><b>Why didn't you use "Beans-style names" for
 consistency?</b></a></li>
 </ol>
-<h3>Collection Interface</h3>
+<h2>Collection Interface</h2>
 <ol>
 <li><a href="#a5"><b>Why doesn't Collection extend Cloneable and
 Serializable?</b></a></li>
@@ -67,7 +67,7 @@
 <li><a href="#a10"><b>Why don't you provide an Iterator.add
 method?</b></a></li>
 </ol>
-<h3>List Interface</h3>
+<h2>List Interface</h2>
 <ol>
 <li><a href="#a11"><b>Why don't you rename the List interface to
 Sequence; doesn't "list" generally suggest "linked list"? Also,
@@ -75,12 +75,12 @@
 <li><a href="#a12"><b>Why don't you rename List's set method to
 replace, to avoid confusion with Set.</b></a></li>
 </ol>
-<h3>Map Interface</h3>
+<h2>Map Interface</h2>
 <ol>
 <li><a href="#a14"><b>Why doesn't Map extend
 Collection?</b></a></li>
 </ol>
-<h3>Iterator Interface</h3>
+<h2>Iterator Interface</h2>
 <ol>
 <li><a href="#a18"><b>Why doesn't Iterator extend
 Enumeration?</b></a></li>
@@ -88,7 +88,7 @@
 that allows you to look at the next element in an iteration without
 advancing the iterator?</b></a></li>
 </ol>
-<h3>Miscellaneous</h3>
+<h2>Miscellaneous</h2>
 <ol>
 <li><a href="#a23"><b>Why did you write a new collections framework
 instead of adopting JGL (a preexisting collections package from
@@ -102,7 +102,7 @@
 modified?</b></a></li>
 </ol>
 <hr>
-<h3>Core Interfaces - General Questions</h3>
+<h2>Core Interfaces - General Questions</h2>
 <ol>
 <li><a id="a1"><b>Why don't you support immutability
 directly in the core collection interfaces so that you can do away
@@ -204,7 +204,7 @@
 Beans style.</li>
 </ol>
 <hr>
-<h3>Collection Interface</h3>
+<h2>Collection Interface</h2>
 <ol>
 <li><a id="a5"><b>Why doesn't Collection extend Cloneable
 and Serializable?</b></a>
@@ -264,7 +264,7 @@
 </li>
 </ol>
 <hr>
-<h3>List Interface</h3>
+<h2>List Interface</h2>
 <ol>
 <li><a id="a11"><b>Why don't you rename the List
 interface to Sequence; doesn't "list" generally suggest "linked
@@ -288,7 +288,7 @@
 </li>
 </ol>
 <hr>
-<h3>Map Interface</h3>
+<h2>Map Interface</h2>
 <ol>
 <li><a id="a14"><b>Why doesn't Map extend
 Collection?</b></a>
@@ -314,7 +314,7 @@
 </li>
 </ol>
 <hr>
-<h3>Iterator Interface</h3>
+<h2>Iterator Interface</h2>
 <ol>
 <li><a id="a18"><b>Why doesn't Iterator extend
 Enumeration?</b></a>
@@ -335,7 +335,7 @@
 </li>
 </ol>
 <hr>
-<h3>Miscellaneous</h3>
+<h2>Miscellaneous</h2>
 <ol>
 <li><a id="a23"><b>Why did you write a new collections
 framework instead of adopting JGL (a preexisting collections
--- a/src/java.base/share/classes/java/util/jar/Attributes.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/jar/Attributes.java	Tue Mar 26 09:05:10 2019 -0400
@@ -34,6 +34,8 @@
 import java.util.Objects;
 import java.util.Set;
 
+import jdk.internal.misc.VM;
+import jdk.internal.vm.annotation.Stable;
 import sun.util.logging.PlatformLogger;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
@@ -454,7 +456,7 @@
         /**
          * Avoid allocation for common Names
          */
-        private static final Map<String, Name> KNOWN_NAMES;
+        private static @Stable Map<String, Name> KNOWN_NAMES;
 
         static final Name of(String name) {
             Name n = KNOWN_NAMES.get(name);
@@ -541,7 +543,7 @@
          * @see <a href="{@docRoot}/../specs/jar/jar.html#jar-manifest">
          *      Manifest and Signature Specification</a>
          */
-        public static final Name MANIFEST_VERSION = new Name("Manifest-Version");
+        public static final Name MANIFEST_VERSION;
 
         /**
          * {@code Name} object for {@code Signature-Version}
@@ -549,13 +551,13 @@
          * @see <a href="{@docRoot}/../specs/jar/jar.html#jar-manifest">
          *      Manifest and Signature Specification</a>
          */
-        public static final Name SIGNATURE_VERSION = new Name("Signature-Version");
+        public static final Name SIGNATURE_VERSION;
 
         /**
          * {@code Name} object for {@code Content-Type}
          * manifest attribute.
          */
-        public static final Name CONTENT_TYPE = new Name("Content-Type");
+        public static final Name CONTENT_TYPE;
 
         /**
          * {@code Name} object for {@code Class-Path}
@@ -563,7 +565,7 @@
          * @see <a href="{@docRoot}/../specs/jar/jar.html#class-path-attribute">
          *      JAR file specification</a>
          */
-        public static final Name CLASS_PATH = new Name("Class-Path");
+        public static final Name CLASS_PATH;
 
         /**
          * {@code Name} object for {@code Main-Class} manifest
@@ -572,7 +574,7 @@
          * with the {@code -jar} command-line option of the
          * {@code java} application launcher.
          */
-        public static final Name MAIN_CLASS = new Name("Main-Class");
+        public static final Name MAIN_CLASS;
 
         /**
          * {@code Name} object for {@code Sealed} manifest attribute
@@ -580,19 +582,19 @@
          * @see <a href="{@docRoot}/../specs/jar/jar.html#package-sealing">
          *      Package Sealing</a>
          */
-        public static final Name SEALED = new Name("Sealed");
+        public static final Name SEALED;
 
         /**
          * {@code Name} object for {@code Extension-List} manifest attribute
          * used for the extension mechanism that is no longer supported.
          */
-        public static final Name EXTENSION_LIST = new Name("Extension-List");
+        public static final Name EXTENSION_LIST;
 
         /**
          * {@code Name} object for {@code Extension-Name} manifest attribute.
          * used for the extension mechanism that is no longer supported.
          */
-        public static final Name EXTENSION_NAME = new Name("Extension-Name");
+        public static final Name EXTENSION_NAME;
 
         /**
          * {@code Name} object for {@code Extension-Installation} manifest attribute.
@@ -600,25 +602,25 @@
          * @deprecated Extension mechanism is no longer supported.
          */
         @Deprecated
-        public static final Name EXTENSION_INSTALLATION = new Name("Extension-Installation");
+        public static final Name EXTENSION_INSTALLATION;
 
         /**
          * {@code Name} object for {@code Implementation-Title}
          * manifest attribute used for package versioning.
          */
-        public static final Name IMPLEMENTATION_TITLE = new Name("Implementation-Title");
+        public static final Name IMPLEMENTATION_TITLE;
 
         /**
          * {@code Name} object for {@code Implementation-Version}
          * manifest attribute used for package versioning.
          */
-        public static final Name IMPLEMENTATION_VERSION = new Name("Implementation-Version");
+        public static final Name IMPLEMENTATION_VERSION;
 
         /**
          * {@code Name} object for {@code Implementation-Vendor}
          * manifest attribute used for package versioning.
          */
-        public static final Name IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor");
+        public static final Name IMPLEMENTATION_VENDOR;
 
         /**
          * {@code Name} object for {@code Implementation-Vendor-Id}
@@ -627,7 +629,7 @@
          * @deprecated Extension mechanism is no longer supported.
          */
         @Deprecated
-        public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
+        public static final Name IMPLEMENTATION_VENDOR_ID;
 
         /**
          * {@code Name} object for {@code Implementation-URL}
@@ -636,25 +638,25 @@
          * @deprecated Extension mechanism is no longer supported.
          */
         @Deprecated
-        public static final Name IMPLEMENTATION_URL = new Name("Implementation-URL");
+        public static final Name IMPLEMENTATION_URL;
 
         /**
          * {@code Name} object for {@code Specification-Title}
          * manifest attribute used for package versioning.
          */
-        public static final Name SPECIFICATION_TITLE = new Name("Specification-Title");
+        public static final Name SPECIFICATION_TITLE;
 
         /**
          * {@code Name} object for {@code Specification-Version}
          * manifest attribute used for package versioning.
          */
-        public static final Name SPECIFICATION_VERSION = new Name("Specification-Version");
+        public static final Name SPECIFICATION_VERSION;
 
         /**
          * {@code Name} object for {@code Specification-Vendor}
          * manifest attribute used for package versioning.
          */
-        public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor");
+        public static final Name SPECIFICATION_VENDOR;
 
         /**
          * {@code Name} object for {@code Multi-Release}
@@ -662,56 +664,91 @@
          *
          * @since   9
          */
-        public static final Name MULTI_RELEASE = new Name("Multi-Release");
+        public static final Name MULTI_RELEASE;
 
         private static void addName(Map<String, Name> names, Name name) {
             names.put(name.name, name);
         }
 
         static {
-            var names = new HashMap<String, Name>(64);
-            addName(names, MANIFEST_VERSION);
-            addName(names, SIGNATURE_VERSION);
-            addName(names, CONTENT_TYPE);
-            addName(names, CLASS_PATH);
-            addName(names, MAIN_CLASS);
-            addName(names, SEALED);
-            addName(names, EXTENSION_LIST);
-            addName(names, EXTENSION_NAME);
-            addName(names, IMPLEMENTATION_TITLE);
-            addName(names, IMPLEMENTATION_VERSION);
-            addName(names, IMPLEMENTATION_VENDOR);
-            addName(names, SPECIFICATION_TITLE);
-            addName(names, SPECIFICATION_VERSION);
-            addName(names, SPECIFICATION_VENDOR);
-            addName(names, MULTI_RELEASE);
+
+            VM.initializeFromArchive(Attributes.Name.class);
+
+            if (KNOWN_NAMES == null) {
+                MANIFEST_VERSION = new Name("Manifest-Version");
+                SIGNATURE_VERSION = new Name("Signature-Version");
+                CONTENT_TYPE = new Name("Content-Type");
+                CLASS_PATH = new Name("Class-Path");
+                MAIN_CLASS = new Name("Main-Class");
+                SEALED = new Name("Sealed");
+                EXTENSION_LIST = new Name("Extension-List");
+                EXTENSION_NAME = new Name("Extension-Name");
+                EXTENSION_INSTALLATION = new Name("Extension-Installation");
+                IMPLEMENTATION_TITLE = new Name("Implementation-Title");
+                IMPLEMENTATION_VERSION = new Name("Implementation-Version");
+                IMPLEMENTATION_VENDOR = new Name("Implementation-Vendor");
+                IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
+                IMPLEMENTATION_URL = new Name("Implementation-URL");
+                SPECIFICATION_TITLE = new Name("Specification-Title");
+                SPECIFICATION_VERSION = new Name("Specification-Version");
+                SPECIFICATION_VENDOR = new Name("Specification-Vendor");
+                MULTI_RELEASE = new Name("Multi-Release");
 
-            // Common attributes used in MANIFEST.MF et.al; adding these has a
-            // small footprint cost, but is likely to be quickly paid for by
-            // reducing allocation when reading and parsing typical manifests
-            addName(names, new Name("Add-Exports"));
-            addName(names, new Name("Add-Opens"));
-            addName(names, new Name("Ant-Version"));
-            addName(names, new Name("Archiver-Version"));
-            addName(names, new Name("Build-Jdk"));
-            addName(names, new Name("Built-By"));
-            addName(names, new Name("Bnd-LastModified"));
-            addName(names, new Name("Bundle-Description"));
-            addName(names, new Name("Bundle-DocURL"));
-            addName(names, new Name("Bundle-License"));
-            addName(names, new Name("Bundle-ManifestVersion"));
-            addName(names, new Name("Bundle-Name"));
-            addName(names, new Name("Bundle-Vendor"));
-            addName(names, new Name("Bundle-Version"));
-            addName(names, new Name("Bundle-SymbolicName"));
-            addName(names, new Name("Created-By"));
-            addName(names, new Name("Export-Package"));
-            addName(names, new Name("Import-Package"));
-            addName(names, new Name("Name"));
-            addName(names, new Name("SHA1-Digest"));
-            addName(names, new Name("X-Compile-Source-JDK"));
-            addName(names, new Name("X-Compile-Target-JDK"));
-            KNOWN_NAMES = names;
+                var names = new HashMap<String, Name>(64);
+                addName(names, MANIFEST_VERSION);
+                addName(names, SIGNATURE_VERSION);
+                addName(names, CONTENT_TYPE);
+                addName(names, CLASS_PATH);
+                addName(names, MAIN_CLASS);
+                addName(names, SEALED);
+                addName(names, EXTENSION_LIST);
+                addName(names, EXTENSION_NAME);
+                addName(names, IMPLEMENTATION_TITLE);
+                addName(names, IMPLEMENTATION_VERSION);
+                addName(names, IMPLEMENTATION_VENDOR);
+                addName(names, SPECIFICATION_TITLE);
+                addName(names, SPECIFICATION_VERSION);
+                addName(names, SPECIFICATION_VENDOR);
+                addName(names, MULTI_RELEASE);
+
+                // Common attributes used in MANIFEST.MF et.al; adding these has a
+                // small footprint cost, but is likely to be quickly paid for by
+                // reducing allocation when reading and parsing typical manifests
+
+                // JDK internal attributes
+                addName(names, new Name("Add-Exports"));
+                addName(names, new Name("Add-Opens"));
+                // LauncherHelper attributes
+                addName(names, new Name("Launcher-Agent-Class"));
+                addName(names, new Name("JavaFX-Application-Class"));
+                // jarsigner attributes
+                addName(names, new Name("Name"));
+                addName(names, new Name("Created-By"));
+                addName(names, new Name("SHA1-Digest"));
+                addName(names, new Name("SHA-256-Digest"));
+                KNOWN_NAMES = Map.copyOf(names);
+            } else {
+                // Even if KNOWN_NAMES was read from archive, we still need
+                // to initialize the public constants
+                MANIFEST_VERSION = KNOWN_NAMES.get("Manifest-Version");
+                SIGNATURE_VERSION = KNOWN_NAMES.get("Signature-Version");
+                CONTENT_TYPE = KNOWN_NAMES.get("Content-Type");
+                CLASS_PATH = KNOWN_NAMES.get("Class-Path");
+                MAIN_CLASS = KNOWN_NAMES.get("Main-Class");
+                SEALED = KNOWN_NAMES.get("Sealed");
+                EXTENSION_LIST = KNOWN_NAMES.get("Extension-List");
+                EXTENSION_NAME = KNOWN_NAMES.get("Extension-Name");
+                EXTENSION_INSTALLATION = KNOWN_NAMES.get("Extension-Installation");
+                IMPLEMENTATION_TITLE = KNOWN_NAMES.get("Implementation-Title");
+                IMPLEMENTATION_VERSION = KNOWN_NAMES.get("Implementation-Version");
+                IMPLEMENTATION_VENDOR = KNOWN_NAMES.get("Implementation-Vendor");
+                IMPLEMENTATION_VENDOR_ID = KNOWN_NAMES.get("Implementation-Vendor-Id");
+                IMPLEMENTATION_URL = KNOWN_NAMES.get("Implementation-URL");
+                SPECIFICATION_TITLE = KNOWN_NAMES.get("Specification-Title");
+                SPECIFICATION_VERSION = KNOWN_NAMES.get("Specification-Version");
+                SPECIFICATION_VENDOR = KNOWN_NAMES.get("Specification-Vendor");
+                MULTI_RELEASE = KNOWN_NAMES.get("Multi-Release");
+            }
         }
     }
 }
--- a/src/java.base/share/classes/java/util/regex/Pattern.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/regex/Pattern.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,7 @@
  * such use.
  *
  *
- * <h3><a id="sum">Summary of regular-expression constructs</a></h3>
+ * <h2><a id="sum">Summary of regular-expression constructs</a></h2>
  *
  * <table class="borderless">
  * <caption style="display:none">Regular expression constructs, and what they match</caption>
@@ -378,7 +378,7 @@
  * <hr>
  *
  *
- * <h3><a id="bs">Backslashes, escapes, and quoting</a></h3>
+ * <h2><a id="bs">Backslashes, escapes, and quoting</a></h2>
  *
  * <p> The backslash character ({@code '\'}) serves to introduce escaped
  * constructs, as defined in the table above, as well as to quote characters
@@ -406,7 +406,7 @@
  * {@code (hello)} the string literal {@code "\\(hello\\)"}
  * must be used.
  *
- * <h3><a id="cc">Character Classes</a></h3>
+ * <h2><a id="cc">Character Classes</a></h2>
  *
  *    <p> Character classes may appear within other character classes, and
  *    may be composed by the union operator (implicit) and the intersection
@@ -449,7 +449,7 @@
  *    character class, while the expression {@code -} becomes a range
  *    forming metacharacter.
  *
- * <h3><a id="lt">Line terminators</a></h3>
+ * <h2><a id="lt">Line terminators</a></h2>
  *
  * <p> A <i>line terminator</i> is a one- or two-character sequence that marks
  * the end of a line of the input character sequence.  The following are
@@ -484,9 +484,9 @@
  * except at the end of input. When in {@link #MULTILINE} mode {@code $}
  * matches just before a line terminator or the end of the input sequence.
  *
- * <h3><a id="cg">Groups and capturing</a></h3>
+ * <h2><a id="cg">Groups and capturing</a></h2>
  *
- * <h4><a id="gnumber">Group number</a></h4>
+ * <h3><a id="gnumber">Group number</a></h3>
  * <p> Capturing groups are numbered by counting their opening parentheses from
  * left to right.  In the expression {@code ((A)(B(C)))}, for example, there
  * are four such groups: </p>
@@ -505,7 +505,7 @@
  * subsequence may be used later in the expression, via a back reference, and
  * may also be retrieved from the matcher once the match operation is complete.
  *
- * <h4><a id="groupname">Group name</a></h4>
+ * <h3><a id="groupname">Group name</a></h3>
  * <p>A capturing group can also be assigned a "name", a {@code named-capturing group},
  * and then be back-referenced later by the "name". Group names are composed of
  * the following characters. The first character must be a {@code letter}.
@@ -534,7 +534,7 @@
  * that do not capture text and do not count towards the group total, or
  * <i>named-capturing</i> group.
  *
- * <h3> Unicode support </h3>
+ * <h2> Unicode support </h2>
  *
  * <p> This class is in conformance with Level 1 of <a
  * href="http://www.unicode.org/reports/tr18/"><i>Unicode Technical
@@ -688,7 +688,7 @@
  * available through the same <code>\p{</code><i>prop</i><code>}</code> syntax where
  * the specified property has the name <code>java<i>methodname</i></code></a>.
  *
- * <h3> Comparison to Perl 5 </h3>
+ * <h2> Comparison to Perl 5 </h2>
  *
  * <p>The {@code Pattern} engine performs traditional NFA-based matching
  * with ordered alternation as occurs in Perl 5.
--- a/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
  * interfaces to offer support for locales beyond the set of locales
  * supported by the Java runtime environment itself.
  *
- * <h3>Packaging of Locale Sensitive Service Provider Implementations</h3>
+ * <h2>Packaging of Locale Sensitive Service Provider Implementations</h2>
  * Implementations of these locale sensitive services can be made available
  * by adding them to the application's class path. A provider identifies itself with a
  * provider-configuration file in the resource directory META-INF/services,
@@ -75,7 +75,7 @@
  * </pre>
  * which is the fully qualified class name of the class implementing
  * <code>DateFormatProvider</code>.
- * <h4>Invocation of Locale Sensitive Services</h4>
+ * <h3>Invocation of Locale Sensitive Services</h3>
  * <p>
  * Locale sensitive factory methods and methods for name retrieval in the
  * <code>java.text</code> and <code>java.util</code> packages invoke
--- a/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/java/util/spi/ResourceBundleProvider.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@
  * factory methods to locate and load the service providers that are deployed as
  * modules via {@link java.util.ServiceLoader ServiceLoader}.
  *
- * <h3>Developing resource bundle services</h3>
+ * <h2>Developing resource bundle services</h2>
  *
  * A service for a resource bundle of a given <em>{@code baseName}</em> must have
  * a fully-qualified class name of the form:
@@ -55,7 +55,7 @@
  * }
  * }</pre></blockquote>
  *
- * <h3>Deploying resource bundle service providers</h3>
+ * <h2>Deploying resource bundle service providers</h2>
  *
  * Resource bundles can be deployed in one or more service providers
  * in modules.  For example, a provider for a service
@@ -114,7 +114,7 @@
  *     provides com.example.app.spi.MyResourcesProvider with com.example.impl.MyResourcesProviderImpl;
  * </pre>
  *
- * <h3><a id="obtain-resource-bundle">Obtaining resource bundles from providers</a></h3>
+ * <h2><a id="obtain-resource-bundle">Obtaining resource bundles from providers</a></h2>
  *
  * The module declaration of the <em>consumer module</em> that calls one of the
  * {@code ResourceBundle.getBundle} factory methods to obtain a resource
--- a/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/net/ssl/HandshakeCompletedEvent.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -162,7 +162,8 @@
      *               array of {@code java.security.cert.Certificate} should
      *               be used instead.
      */
-    @Deprecated(since="9")
+    @SuppressWarnings("removal")
+    @Deprecated(since="9", forRemoval=true)
     public javax.security.cert.X509Certificate [] getPeerCertificateChain()
             throws SSLPeerUnverifiedException
     {
--- a/src/java.base/share/classes/javax/net/ssl/SSLSession.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/net/ssl/SSLSession.java	Tue Mar 26 09:05:10 2019 -0400
@@ -282,7 +282,8 @@
      *               array of {@code java.security.cert.Certificate} should
      *               be used instead.
      */
-    @Deprecated(since="9")
+    @SuppressWarnings("removal")
+    @Deprecated(since="9", forRemoval=true)
     public javax.security.cert.X509Certificate [] getPeerCertificateChain()
             throws SSLPeerUnverifiedException;
 
--- a/src/java.base/share/classes/javax/security/cert/Certificate.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/security/cert/Certificate.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,8 @@
  *
  * @author Hemma Prafullchandra
  */
-@Deprecated(since="9")
+@SuppressWarnings("removal")
+@Deprecated(since="9", forRemoval=true)
 public abstract class Certificate {
 
     /**
--- a/src/java.base/share/classes/javax/security/cert/CertificateEncodingException.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/security/cert/CertificateEncodingException.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,8 @@
  * @author Hemma Prafullchandra
  * @deprecated Use the classes in {@code java.security.cert} instead.
  */
-@Deprecated(since="9")
+@SuppressWarnings("removal")
+@Deprecated(since="9", forRemoval=true)
 public class CertificateEncodingException extends CertificateException {
 
     private static final long serialVersionUID = -8187642723048403470L;
--- a/src/java.base/share/classes/javax/security/cert/CertificateException.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/security/cert/CertificateException.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,7 @@
  * @see Certificate
  * @deprecated Use the classes in {@code java.security.cert} instead.
  */
-@Deprecated(since="9")
+@Deprecated(since="9", forRemoval=true)
 public class CertificateException extends Exception {
 
     private static final long serialVersionUID = -5757213374030785290L;
--- a/src/java.base/share/classes/javax/security/cert/CertificateExpiredException.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/security/cert/CertificateExpiredException.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,8 @@
  * @author Hemma Prafullchandra
  * @deprecated Use the classes in {@code java.security.cert} instead.
  */
-@Deprecated(since="9")
+@SuppressWarnings("removal")
+@Deprecated(since="9", forRemoval=true)
 public class CertificateExpiredException extends CertificateException {
 
     private static final long serialVersionUID = 5091601212177261883L;
--- a/src/java.base/share/classes/javax/security/cert/CertificateNotYetValidException.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/security/cert/CertificateNotYetValidException.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,8 @@
  * @author Hemma Prafullchandra
  * @deprecated Use the classes in {@code java.security.cert} instead.
  */
-@Deprecated(since="9")
+@SuppressWarnings("removal")
+@Deprecated(since="9", forRemoval=true)
 public class CertificateNotYetValidException extends CertificateException {
 
     private static final long serialVersionUID = -8976172474266822818L;
--- a/src/java.base/share/classes/javax/security/cert/CertificateParsingException.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/security/cert/CertificateParsingException.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,8 @@
  * @author Hemma Prafullchandra
  * @deprecated Use the classes in {@code java.security.cert} instead.
  */
-@Deprecated(since="9")
+@SuppressWarnings("removal")
+@Deprecated(since="9", forRemoval=true)
 public class CertificateParsingException extends CertificateException {
 
     private static final long serialVersionUID = -8449352422951136229L;
--- a/src/java.base/share/classes/javax/security/cert/X509Certificate.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/javax/security/cert/X509Certificate.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -126,7 +126,8 @@
  * @see java.security.Security security properties
  * @deprecated Use the classes in {@code java.security.cert} instead.
  */
-@Deprecated(since="9")
+@SuppressWarnings("removal")
+@Deprecated(since="9", forRemoval=true)
 public abstract class X509Certificate extends Certificate {
 
     /*
--- a/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java	Tue Mar 26 09:05:10 2019 -0400
@@ -103,10 +103,13 @@
         DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.isEmpty() : false;
 
         // This property will be removed in a later release
-        p = props.getProperty("jdk.net.URLClassPath.disableClassPathURLCheck", "true");
+        p = props.getProperty("jdk.net.URLClassPath.disableClassPathURLCheck");
+        DISABLE_CP_URL_CHECK = p != null ? p.equals("true") || p.isEmpty() : false;
 
-        DISABLE_CP_URL_CHECK = p != null ? p.equals("true") || p.isEmpty() : false;
-        DEBUG_CP_URL_CHECK = "debug".equals(p);
+        // Print a message for each Class-Path entry that is ignored (assuming
+        // the check is not disabled).
+        p = props.getProperty("jdk.net.URLClassPath.showIgnoredClassPathEntries");
+        DEBUG_CP_URL_CHECK = p != null ? p.equals("true") || p.isEmpty() : false;
     }
 
     /* The original search path of URLs. */
--- a/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017 Oracle and/or its affiliates. All rights reserved.
+ * 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/net/PlatformSocketImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.net;
+
+/**
+ * Implemented by the platform's SocketImpl implementations.
+ */
+
+public interface PlatformSocketImpl {
+}
--- a/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018 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
--- a/src/java.base/share/classes/sun/nio/ch/IOStatus.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/ch/IOStatus.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,4 +81,12 @@
         return ((n > EOF) || (n < UNSUPPORTED_CASE));
     }
 
+    /**
+     * Returns true if the error code is UNAVAILABLE or INTERRUPTED, the
+     * error codes to indicate that an I/O operation can be retried.
+     */
+    static boolean okayToRetry(long n) {
+        return (n == IOStatus.UNAVAILABLE) || (n == IOStatus.INTERRUPTED);
+    }
+
 }
--- a/src/java.base/share/classes/sun/nio/ch/Net.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/ch/Net.java	Tue Mar 26 09:05:10 2019 -0400
@@ -310,6 +310,12 @@
     static final ExtendedSocketOptions extendedOptions =
             ExtendedSocketOptions.getInstance();
 
+    static void setSocketOption(FileDescriptor fd, SocketOption<?> name, Object value)
+        throws IOException
+    {
+        setSocketOption(fd, Net.UNSPEC, name, value);
+    }
+
     static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
                                 SocketOption<?> name, Object value)
         throws IOException
@@ -372,8 +378,13 @@
         setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6);
     }
 
-    static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
-                                  SocketOption<?> name)
+    static Object getSocketOption(FileDescriptor fd, SocketOption<?> name)
+        throws IOException
+    {
+        return getSocketOption(fd, Net.UNSPEC, name);
+    }
+
+    static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, SocketOption<?> name)
         throws IOException
     {
         Class<?> type = name.type();
@@ -426,8 +437,7 @@
         return socket(UNSPEC, stream);
     }
 
-    static FileDescriptor socket(ProtocolFamily family, boolean stream)
-        throws IOException {
+    static FileDescriptor socket(ProtocolFamily family, boolean stream) throws IOException {
         boolean preferIPv6 = isIPv6Available() &&
             (family != StandardProtocolFamily.INET);
         return IOUtil.newFD(socket0(preferIPv6, stream, false, fastLoopback));
@@ -482,6 +492,10 @@
                                        int remotePort)
         throws IOException;
 
+    public static native int accept(FileDescriptor fd,
+                                    FileDescriptor newfd,
+                                    InetSocketAddress[] isaa)
+        throws IOException;
 
     public static final int SHUT_RD = 0;
     public static final int SHUT_WR = 1;
@@ -521,21 +535,44 @@
                                              int level, int opt, int arg, boolean isIPv6)
         throws IOException;
 
+    /**
+     * Polls a file descriptor for events.
+     * @param timeout the timeout to wait; 0 to not wait, -1 to wait indefinitely
+     * @return the polled events or 0 if no events are polled
+     */
     static native int poll(FileDescriptor fd, int events, long timeout)
         throws IOException;
 
     /**
+     * Performs a non-blocking poll of a file descriptor.
+     * @return the polled events or 0 if no events are polled
+     */
+    static int pollNow(FileDescriptor fd, int events) throws IOException {
+        return poll(fd, events, 0);
+    }
+
+    /**
      * Polls a connecting socket to test if the connection has been established.
      *
      * @apiNote This method is public to allow it be used by code in jdk.sctp.
      *
      * @param timeout the timeout to wait; 0 to not wait, -1 to wait indefinitely
-     * @return 1 if connected, 0 if not connected, or IOS_INTERRUPTED
+     * @return true if connected
      */
-    public static native int pollConnect(FileDescriptor fd, long timeout)
+    public static native boolean pollConnect(FileDescriptor fd, long timeout)
         throws IOException;
 
     /**
+     * Performs a non-blocking poll of a connecting socket to test if the
+     * connection has been established.
+     *
+     * @return true if connected
+     */
+    static boolean pollConnectNow(FileDescriptor fd) throws IOException {
+        return pollConnect(fd, 0);
+    }
+
+    /**
      * Return the number of bytes in the socket input buffer.
      */
     static native int available(FileDescriptor fd) throws IOException;
--- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -58,7 +58,7 @@
     implements SelChImpl
 {
     // Used to make native close and configure calls
-    private static NativeDispatcher nd;
+    private static final NativeDispatcher nd = new SocketDispatcher();
 
     // Our file descriptor
     private final FileDescriptor fd;
@@ -97,7 +97,7 @@
 
     ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
         super(sp);
-        this.fd =  Net.serverSocket(true);
+        this.fd = Net.serverSocket(true);
         this.fdVal = IOUtil.fdVal(fd);
     }
 
@@ -261,46 +261,44 @@
 
     @Override
     public SocketChannel accept() throws IOException {
+        int n = 0;
+        FileDescriptor newfd = new FileDescriptor();
+        InetSocketAddress[] isaa = new InetSocketAddress[1];
+
         acceptLock.lock();
         try {
-            int n = 0;
-            FileDescriptor newfd = new FileDescriptor();
-            InetSocketAddress[] isaa = new InetSocketAddress[1];
-
             boolean blocking = isBlocking();
             try {
                 begin(blocking);
                 do {
-                    n = accept(this.fd, newfd, isaa);
+                    n = Net.accept(this.fd, newfd, isaa);
                 } while (n == IOStatus.INTERRUPTED && isOpen());
             } finally {
                 end(blocking, n > 0);
                 assert IOStatus.check(n);
             }
 
-            if (n < 1)
-                return null;
+        } finally {
+            acceptLock.unlock();
+        }
 
+        if (n < 1)
+            return null;
+
+        InetSocketAddress isa = isaa[0];
+        try {
             // newly accepted socket is initially in blocking mode
             IOUtil.configureBlocking(newfd, true);
 
-            InetSocketAddress isa = isaa[0];
-            SocketChannel sc = new SocketChannelImpl(provider(), newfd, isa);
-
             // check permitted to accept connections from the remote address
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
-                try {
-                    sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort());
-                } catch (SecurityException x) {
-                    sc.close();
-                    throw x;
-                }
+                sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort());
             }
-            return sc;
-
-        } finally {
-            acceptLock.unlock();
+            return new SocketChannelImpl(provider(), newfd, isa);
+        } catch (Exception e) {
+            nd.close(newfd);
+            throw e;
         }
     }
 
@@ -508,38 +506,4 @@
         sb.append(']');
         return sb.toString();
     }
-
-    /**
-     * Accept a connection on a socket.
-     *
-     * @implNote Wrap native call to allow instrumentation.
-     */
-    private int accept(FileDescriptor ssfd,
-                       FileDescriptor newfd,
-                       InetSocketAddress[] isaa)
-        throws IOException
-    {
-        return accept0(ssfd, newfd, isaa);
-    }
-
-    // -- Native methods --
-
-    // Accepts a new connection, setting the given file descriptor to refer to
-    // the new socket and setting isaa[0] to the socket's remote address.
-    // Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no
-    // connections are pending) or IOStatus.INTERRUPTED.
-    //
-    private native int accept0(FileDescriptor ssfd,
-                               FileDescriptor newfd,
-                               InetSocketAddress[] isaa)
-        throws IOException;
-
-    private static native void initIDs();
-
-    static {
-        IOUtil.load();
-        initIDs();
-        nd = new SocketDispatcher();
-    }
-
 }
--- a/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -216,6 +216,11 @@
                 }
             }
         }
+
+        @Override
+        public int available() throws IOException {
+            return sc.available();
+        }
     }
 
     private InputStream socketInputStream = null;
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -32,6 +32,7 @@
 import java.net.ProtocolFamily;
 import java.net.Socket;
 import java.net.SocketAddress;
+import java.net.SocketException;
 import java.net.SocketOption;
 import java.net.StandardProtocolFamily;
 import java.net.StandardSocketOptions;
@@ -52,6 +53,7 @@
 import java.util.Set;
 import java.util.concurrent.locks.ReentrantLock;
 
+import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
 import sun.net.ext.ExtendedSocketOptions;
 import sun.net.util.SocketExceptions;
@@ -85,6 +87,9 @@
     private volatile boolean isInputClosed;
     private volatile boolean isOutputClosed;
 
+    // Connection reset protected by readLock
+    private boolean connectionReset;
+
     // -- The following fields are protected by stateLock
 
     // set true when exclusive binding is on and SO_REUSEADDR is emulated
@@ -230,7 +235,7 @@
             }
 
             // no options that require special handling
-            Net.setSocketOption(fd, Net.UNSPEC, name, value);
+            Net.setSocketOption(fd, name, value);
             return this;
         }
     }
@@ -260,7 +265,7 @@
             }
 
             // no options that require special handling
-            return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
+            return (T) Net.getSocketOption(fd, name);
         }
     }
 
@@ -334,6 +339,10 @@
         }
     }
 
+    private void throwConnectionReset() throws SocketException {
+        throw new SocketException("Connection reset");
+    }
+
     @Override
     public int read(ByteBuffer buf) throws IOException {
         Objects.requireNonNull(buf);
@@ -345,6 +354,10 @@
             try {
                 beginRead(blocking);
 
+                // check if connection has been reset
+                if (connectionReset)
+                    throwConnectionReset();
+
                 // check if input is shutdown
                 if (isInputClosed)
                     return IOStatus.EOF;
@@ -356,6 +369,9 @@
                 } else {
                     n = IOUtil.read(fd, buf, -1, nd);
                 }
+            } catch (ConnectionResetException e) {
+                connectionReset = true;
+                throwConnectionReset();
             } finally {
                 endRead(blocking, n > 0);
                 if (n <= 0 && isInputClosed)
@@ -380,6 +396,10 @@
             try {
                 beginRead(blocking);
 
+                // check if connection has been reset
+                if (connectionReset)
+                    throwConnectionReset();
+
                 // check if input is shutdown
                 if (isInputClosed)
                     return IOStatus.EOF;
@@ -391,6 +411,9 @@
                 } else {
                     n = IOUtil.read(fd, dsts, offset, length, nd);
                 }
+            } catch (ConnectionResetException e) {
+                connectionReset = true;
+                throwConnectionReset();
             } finally {
                 endRead(blocking, n > 0);
                 if (n <= 0 && isInputClosed)
@@ -769,15 +792,13 @@
                     boolean connected = false;
                     try {
                         beginFinishConnect(blocking);
-                        int n = 0;
                         if (blocking) {
                             do {
-                                n = Net.pollConnect(fd, -1);
-                            } while ((n == 0 || n == IOStatus.INTERRUPTED) && isOpen());
+                                connected = Net.pollConnect(fd, -1);
+                            } while (!connected && isOpen());
                         } else {
-                            n = Net.pollConnect(fd, 0);
+                            connected = Net.pollConnect(fd, 0);
                         }
-                        connected = (n > 0);
                     } finally {
                         endFinishConnect(blocking, connected);
                     }
@@ -1007,6 +1028,20 @@
     }
 
     /**
+     * Return the number of bytes in the socket input buffer.
+     */
+    int available() throws IOException {
+        synchronized (stateLock) {
+            ensureOpenAndConnected();
+            if (isInputClosed) {
+                return 0;
+            } else {
+                return Net.available(fd);
+            }
+        }
+    }
+
+    /**
      * Translates native poll revent ops into a ready operation ops
      */
     public boolean translateReadyOps(int ops, int initialOps, SelectionKeyImpl ski) {
--- a/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/NewSessionTicket.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,6 @@
 import java.security.SecureRandom;
 import java.text.MessageFormat;
 import java.util.Locale;
-import java.util.Optional;
 import javax.crypto.SecretKey;
 import javax.net.ssl.SSLHandshakeException;
 import sun.security.ssl.PskKeyExchangeModesExtension.PskKeyExchangeModesSpec;
@@ -224,9 +223,9 @@
             SessionId newId = new SessionId(true,
                 shc.sslContext.getSecureRandom());
 
-            Optional<SecretKey> resumptionMasterSecret =
+            SecretKey resumptionMasterSecret =
                 shc.handshakeSession.getResumptionMasterSecret();
-            if (!resumptionMasterSecret.isPresent()) {
+            if (resumptionMasterSecret == null) {
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(
                         "Session has no resumption secret. No ticket sent.");
@@ -239,7 +238,7 @@
             byte[] nonceArr = nonce.toByteArray();
             SecretKey psk = derivePreSharedKey(
                     shc.negotiatedCipherSuite.hashAlg,
-                    resumptionMasterSecret.get(), nonceArr);
+                    resumptionMasterSecret, nonceArr);
 
             int sessionTimeoutSeconds = sessionCache.getSessionTimeout();
             if (sessionTimeoutSeconds > MAX_TICKET_LIFETIME) {
@@ -354,9 +353,9 @@
 
             SSLSessionImpl sessionToSave = hc.conContext.conSession;
 
-            Optional<SecretKey> resumptionMasterSecret =
+            SecretKey resumptionMasterSecret =
                 sessionToSave.getResumptionMasterSecret();
-            if (!resumptionMasterSecret.isPresent()) {
+            if (resumptionMasterSecret == null) {
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(
                     "Session has no resumption master secret. Ignoring ticket.");
@@ -366,7 +365,7 @@
 
             // derive the PSK
             SecretKey psk = derivePreSharedKey(
-                sessionToSave.getSuite().hashAlg, resumptionMasterSecret.get(),
+                sessionToSave.getSuite().hashAlg, resumptionMasterSecret,
                 nstm.ticketNonce);
 
             // create and cache the new session
--- a/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/PreSharedKeyExtension.java	Tue Mar 26 09:05:10 2019 -0400
@@ -33,7 +33,6 @@
 import java.util.Locale;
 import java.util.Arrays;
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Collection;
 import javax.crypto.Mac;
 import javax.crypto.SecretKey;
@@ -402,7 +401,7 @@
     private static boolean canRejoin(ClientHelloMessage clientHello,
         ServerHandshakeContext shc, SSLSessionImpl s) {
 
-        boolean result = s.isRejoinable() && s.getPreSharedKey().isPresent();
+        boolean result = s.isRejoinable() && (s.getPreSharedKey() != null);
 
         // Check protocol version
         if (result && s.getProtocolVersion() != shc.negotiatedProtocol) {
@@ -530,12 +529,11 @@
     private static void checkBinder(ServerHandshakeContext shc,
             SSLSessionImpl session,
             HandshakeHash pskBinderHash, byte[] binder) throws IOException {
-        Optional<SecretKey> pskOpt = session.getPreSharedKey();
-        if (!pskOpt.isPresent()) {
+        SecretKey psk = session.getPreSharedKey();
+        if (psk == null) {
             throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
                     "Session has no PSK");
         }
-        SecretKey psk = pskOpt.get();
 
         SecretKey binderKey = deriveBinderKey(shc, psk, session);
         byte[] computedBinder =
@@ -647,27 +645,28 @@
             }
 
             // The session must have a pre-shared key
-            Optional<SecretKey> pskOpt = chc.resumingSession.getPreSharedKey();
-            if (!pskOpt.isPresent()) {
+            SecretKey psk = chc.resumingSession.getPreSharedKey();
+            if (psk == null) {
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine("Existing session has no PSK.");
                 }
                 return null;
             }
-            SecretKey psk = pskOpt.get();
+
             // 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 (chc.pskIdentity == null) {
+                chc.pskIdentity = chc.resumingSession.consumePskIdentity();
+            }
+
+            if (chc.pskIdentity == null) {
                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(
                         "PSK has no identity, or identity was already used");
                 }
                 return null;
             }
-            chc.pskIdentity = pskIdOpt.get();
 
             //The session cannot be used again. Remove it from the cache.
             SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
--- a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
-import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import javax.crypto.SecretKey;
@@ -286,18 +285,20 @@
         return masterSecret;
     }
 
-    Optional<SecretKey> getResumptionMasterSecret() {
-        return Optional.ofNullable(resumptionMasterSecret);
+    SecretKey getResumptionMasterSecret() {
+        return resumptionMasterSecret;
     }
 
-    synchronized Optional<SecretKey> getPreSharedKey() {
-        return Optional.ofNullable(preSharedKey);
+    synchronized SecretKey getPreSharedKey() {
+        return preSharedKey;
     }
 
-    synchronized Optional<SecretKey> consumePreSharedKey() {
-        Optional<SecretKey> result = Optional.ofNullable(preSharedKey);
-        preSharedKey = null;
-        return result;
+    synchronized SecretKey consumePreSharedKey() {
+        try {
+            return preSharedKey;
+        } finally {
+            preSharedKey = null;
+        }
     }
 
     int getTicketAgeAdd() {
@@ -312,10 +313,12 @@
      * be used once. This method will return the identity and then clear it
      * so it cannot be used again.
      */
-    synchronized Optional<byte[]> consumePskIdentity() {
-        Optional<byte[]> result = Optional.ofNullable(pskIdentity);
-        pskIdentity = null;
-        return result;
+    synchronized byte[] consumePskIdentity() {
+        try {
+            return pskIdentity;
+        } finally {
+            pskIdentity = null;
+        }
     }
 
     void setPeerCertificates(X509Certificate[] peer) {
@@ -597,7 +600,8 @@
      *  Use {@code getPeerCertificates()} instead.
      */
     @Override
-    @Deprecated
+    @SuppressWarnings("removal")
+    @Deprecated(since="9", forRemoval=true)
     public javax.security.cert.X509Certificate[] getPeerCertificateChain()
             throws SSLPeerUnverifiedException {
         //
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -342,15 +342,8 @@
 
     @Override
     public synchronized SSLSession getHandshakeSession() {
-        if (conContext.handshakeContext != null) {
-            synchronized (this) {
-                if (conContext.handshakeContext != null) {
-                    return conContext.handshakeContext.handshakeSession;
-                }
-            }
-        }
-
-        return null;
+        return conContext.handshakeContext == null ?
+                null : conContext.handshakeContext.handshakeSession;
     }
 
     @Override
--- a/src/java.base/share/classes/sun/security/ssl/ServerHello.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ServerHello.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,6 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Optional;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.IvParameterSpec;
 import javax.net.ssl.SSLException;
@@ -544,7 +543,7 @@
                         shc.negotiatedProtocol, shc.negotiatedCipherSuite);
 
                 setUpPskKD(shc,
-                        shc.resumingSession.consumePreSharedKey().get());
+                        shc.resumingSession.consumePreSharedKey());
 
                 // The session can't be resumed again---remove it from cache
                 SSLSessionContextImpl sessionCache = (SSLSessionContextImpl)
@@ -1223,16 +1222,16 @@
                         chc.sslConfig.maximumPacketSize);
             } else {
                 // The PSK is consumed to allow it to be deleted
-                Optional<SecretKey> psk =
+                SecretKey psk =
                         chc.resumingSession.consumePreSharedKey();
-                if(!psk.isPresent()) {
+                if(psk == null) {
                     throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
                     "No PSK available. Unable to resume.");
                 }
 
                 chc.handshakeSession = chc.resumingSession;
 
-                setUpPskKD(chc, psk.get());
+                setUpPskKD(chc, psk);
             }
 
             //
--- a/src/java.base/share/classes/sun/security/util/IOUtils.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/share/classes/sun/security/util/IOUtils.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
--- a/src/java.base/unix/classes/java/io/UnixFileSystem.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/classes/java/io/UnixFileSystem.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,10 +51,12 @@
 
     /* -- Normalization and construction -- */
 
+    @Override
     public char getSeparator() {
         return slash;
     }
 
+    @Override
     public char getPathSeparator() {
         return colon;
     }
@@ -84,6 +86,7 @@
     /* Check that the given pathname is normal.  If not, invoke the real
        normalizer on the part of the pathname that requires normalization.
        This way we iterate through the whole pathname string only once. */
+    @Override
     public String normalize(String pathname) {
         int n = pathname.length();
         char prevChar = 0;
@@ -97,11 +100,13 @@
         return pathname;
     }
 
+    @Override
     public int prefixLength(String pathname) {
         if (pathname.isEmpty()) return 0;
         return (pathname.charAt(0) == '/') ? 1 : 0;
     }
 
+    @Override
     public String resolve(String parent, String child) {
         if (child.isEmpty()) return parent;
         if (child.charAt(0) == '/') {
@@ -112,10 +117,12 @@
         return parent + '/' + child;
     }
 
+    @Override
     public String getDefaultParent() {
         return "/";
     }
 
+    @Override
     public String fromURIPath(String path) {
         String p = path;
         if (p.endsWith("/") && (p.length() > 1)) {
@@ -128,10 +135,12 @@
 
     /* -- Path operations -- */
 
+    @Override
     public boolean isAbsolute(File f) {
         return (f.getPrefixLength() != 0);
     }
 
+    @Override
     public String resolve(File f) {
         if (isAbsolute(f)) return f.getPath();
         SecurityManager sm = System.getSecurityManager();
@@ -153,6 +162,7 @@
     // canonicalization algorithm
     private final ExpiringCache javaHomePrefixCache;
 
+    @Override
     public String canonicalize(String path) throws IOException {
         if (!useCanonCaches) {
             return canonicalize0(path);
@@ -246,6 +256,7 @@
 
     public native int getBooleanAttributes0(File f);
 
+    @Override
     public int getBooleanAttributes(File f) {
         int rv = getBooleanAttributes0(f);
         String name = f.getName();
@@ -253,15 +264,25 @@
         return rv | (hidden ? BA_HIDDEN : 0);
     }
 
+    @Override
     public native boolean checkAccess(File f, int access);
+
+    @Override
     public native long getLastModifiedTime(File f);
+
+    @Override
     public native long getLength(File f);
+
+    @Override
     public native boolean setPermission(File f, int access, boolean enable, boolean owneronly);
 
     /* -- File operations -- */
 
+    @Override
     public native boolean createFileExclusively(String path)
         throws IOException;
+
+    @Override
     public boolean delete(File f) {
         // Keep canonicalization caches in sync after file deletion
         // and renaming operations. Could be more clever than this
@@ -277,8 +298,14 @@
         return delete0(f);
     }
     private native boolean delete0(File f);
+
+    @Override
     public native String[] list(File f);
+
+    @Override
     public native boolean createDirectory(File f);
+
+    @Override
     public boolean rename(File f1, File f2) {
         // Keep canonicalization caches in sync after file deletion
         // and renaming operations. Could be more clever than this
@@ -294,12 +321,16 @@
         return rename0(f1, f2);
     }
     private native boolean rename0(File f1, File f2);
+
+    @Override
     public native boolean setLastModifiedTime(File f, long time);
+
+    @Override
     public native boolean setReadOnly(File f);
 
-
     /* -- Filesystem interface -- */
 
+    @Override
     public File[] listRoots() {
         try {
             SecurityManager security = System.getSecurityManager();
@@ -313,12 +344,15 @@
     }
 
     /* -- Disk usage -- */
+
+    @Override
     public native long getSpace(File f, int t);
 
     /* -- Basic infrastructure -- */
 
     private native long getNameMax0(String path);
 
+    @Override
     public int getNameMax(String path) {
         long nameMax = getNameMax0(path);
         if (nameMax > Integer.MAX_VALUE) {
@@ -327,10 +361,12 @@
         return (int)nameMax;
     }
 
+    @Override
     public int compare(File f1, File f2) {
         return f1.getPath().compareTo(f2.getPath());
     }
 
+    @Override
     public int hashCode(File f) {
         return f.getPath().hashCode() ^ 1234321;
     }
@@ -341,5 +377,4 @@
     static {
         initIDs();
     }
-
 }
--- a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,13 +34,28 @@
  */
 
 class SocketDispatcher extends NativeDispatcher {
+    SocketDispatcher() { }
 
+    /**
+     * Reads up to len bytes from a socket with special handling for "connection
+     * reset".
+     *
+     * @throws sun.net.ConnectionResetException if connection reset is detected
+     * @throws IOException if another I/O error occurs
+     */
     int read(FileDescriptor fd, long address, int len) throws IOException {
-        return FileDispatcherImpl.read0(fd, address, len);
+        return read0(fd, address, len);
     }
 
+    /**
+     * Scattering read from a socket into len buffers with special handling for
+     * "connection reset".
+     *
+     * @throws sun.net.ConnectionResetException if connection reset is detected
+     * @throws IOException if another I/O error occurs
+     */
     long readv(FileDescriptor fd, long address, int len) throws IOException {
-        return FileDispatcherImpl.readv0(fd, address, len);
+        return readv0(fd, address, len);
     }
 
     int write(FileDescriptor fd, long address, int len) throws IOException {
@@ -58,4 +73,16 @@
     void preClose(FileDescriptor fd) throws IOException {
         FileDispatcherImpl.preClose0(fd);
     }
+
+    // -- Native methods --
+
+    private static native int read0(FileDescriptor fd, long address, int len)
+        throws IOException;
+
+    private static native long readv0(FileDescriptor fd, long address, int len)
+        throws IOException;
+
+    static {
+        IOUtil.load();
+    }
 }
--- a/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@
         Throwable exc = null;
         try {
             begin();
-            int n = accept(this.fd, newfd, isaa);
+            int n = Net.accept(this.fd, newfd, isaa);
 
             // spurious wakeup, is this possible?
             if (n == IOStatus.UNAVAILABLE) {
@@ -221,7 +221,7 @@
                         SecurityManager sm = System.getSecurityManager();
                         if (sm != null) {
                             sm.checkAccept(remote.getAddress().getHostAddress(),
-                                           remote.getPort());
+                                    remote.getPort());
                         }
                         return null;
                     }
@@ -230,7 +230,7 @@
                 SecurityManager sm = System.getSecurityManager();
                 if (sm != null) {
                     sm.checkAccept(remote.getAddress().getHostAddress(),
-                                   remote.getPort());
+                            remote.getPort());
                 }
             }
         } catch (SecurityException x) {
@@ -277,7 +277,7 @@
         try {
             begin();
 
-            int n = accept(this.fd, newfd, isaa);
+            int n = Net.accept(this.fd, newfd, isaa);
             if (n == IOStatus.UNAVAILABLE) {
 
                 // need calling context when there is security manager as
@@ -294,7 +294,7 @@
                         this.acceptAttachment = att;
                     }
                     this.acceptAcc = (System.getSecurityManager() == null) ?
-                        null : AccessController.getContext();
+                            null : AccessController.getContext();
                     this.acceptPending = true;
                 }
 
@@ -331,33 +331,4 @@
             return null;
         }
     }
-
-    /**
-     * Accept a connection on a socket.
-     *
-     * @implNote Wrap native call to allow instrumentation.
-     */
-    private int accept(FileDescriptor ssfd, FileDescriptor newfd,
-                       InetSocketAddress[] isaa)
-        throws IOException
-    {
-        return accept0(ssfd, newfd, isaa);
-    }
-
-    // -- Native methods --
-
-    private static native void initIDs();
-
-    // Accepts a new connection, setting the given file descriptor to refer to
-    // the new socket and setting isaa[0] to the socket's remote address.
-    // Returns 1 on success, or IOStatus.UNAVAILABLE.
-    //
-    private native int accept0(FileDescriptor ssfd, FileDescriptor newfd,
-                               InetSocketAddress[] isaa)
-        throws IOException;
-
-    static {
-        IOUtil.load();
-        initIDs();
-    }
 }
--- a/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,8 @@
 import java.util.concurrent.*;
 import java.io.IOException;
 import java.io.FileDescriptor;
+
+import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
 import sun.net.util.SocketExceptions;
 import sun.security.action.GetPropertyAction;
@@ -415,6 +417,8 @@
             enableReading();
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
+            if (x instanceof ConnectionResetException)
+                x = new IOException(x.getMessage());
             exc = x;
         } finally {
             // restart poll in case of concurrent write
@@ -546,6 +550,8 @@
         } catch (Throwable x) {
             if (x instanceof ClosedChannelException)
                 x = new AsynchronousCloseException();
+            if (x instanceof ConnectionResetException)
+                x = new IOException(x.getMessage());
             exc = x;
         } finally {
             if (!pending)
--- a/src/java.base/unix/native/libjava/UnixFileSystem_md.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/native/libjava/UnixFileSystem_md.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -168,7 +168,9 @@
     default: assert(0);
     }
     WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
-        if (access(path, mode) == 0) {
+        int res;
+        RESTARTABLE(access(path, mode), res);
+        if (res == 0) {
             rv = JNI_TRUE;
         }
     } END_PLATFORM_STRING(env, path);
@@ -188,6 +190,7 @@
     WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
         int amode = 0;
         int mode;
+        int res;
         switch (access) {
         case java_io_FileSystem_ACCESS_READ:
             if (owneronly)
@@ -215,7 +218,8 @@
                 mode |= amode;
             else
                 mode &= ~amode;
-            if (chmod(path, mode) >= 0) {
+            RESTARTABLE(chmod(path, mode), res);
+            if (res == 0) {
                 rv = JNI_TRUE;
             }
         }
@@ -280,10 +284,10 @@
             fd = handleOpen(path, O_RDWR | O_CREAT | O_EXCL, 0666);
             if (fd < 0) {
                 if (errno != EEXIST)
-                    JNU_ThrowIOExceptionWithLastError(env, path);
+                    JNU_ThrowIOExceptionWithLastError(env, "Could not open file");
             } else {
                 if (close(fd) == -1)
-                    JNU_ThrowIOExceptionWithLastError(env, path);
+                    JNU_ThrowIOExceptionWithLastError(env, "Could not close file");
                 rv = JNI_TRUE;
             }
         }
@@ -355,13 +359,15 @@
     closedir(dir);
 
     /* Copy the final results into an appropriately-sized array */
-    old = rv;
-    rv = (*env)->NewObjectArray(env, len, str_class, NULL);
-    if (rv == NULL) {
-        return NULL;
-    }
-    if (JNU_CopyObjectArray(env, rv, old, len) < 0) {
-        return NULL;
+    if (len < maxlen) {
+        old = rv;
+        rv = (*env)->NewObjectArray(env, len, str_class, NULL);
+        if (rv == NULL) {
+            return NULL;
+        }
+        if (JNU_CopyObjectArray(env, rv, old, len) < 0) {
+            return NULL;
+        }
     }
     return rv;
 
@@ -446,8 +452,10 @@
 
     WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
         int mode;
+        int res;
         if (statMode(path, &mode)) {
-            if (chmod(path, mode & ~(S_IWUSR | S_IWGRP | S_IWOTH)) >= 0) {
+            RESTARTABLE(chmod(path, mode & ~(S_IWUSR | S_IWGRP | S_IWOTH)), res);
+            if (res == 0) {
                 rv = JNI_TRUE;
             }
         }
@@ -466,6 +474,7 @@
         struct statfs fsstat;
 #else
         struct statvfs64 fsstat;
+        int res;
 #endif
         memset(&fsstat, 0, sizeof(fsstat));
 #ifdef MACOSX
@@ -488,7 +497,8 @@
             }
         }
 #else
-        if (statvfs64(path, &fsstat) == 0) {
+        RESTARTABLE(statvfs64(path, &fsstat), res);
+        if (res == 0) {
             switch(t) {
             case java_io_FileSystem_SPACE_TOTAL:
                 rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
--- a/src/java.base/unix/native/libjava/io_util_md.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/native/libjava/io_util_md.h	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,11 +93,10 @@
 /*
  * Retry the operation if it is interrupted
  */
-#define RESTARTABLE(_cmd, _result) do { \
-    do { \
-        _result = _cmd; \
-    } while((_result == -1) && (errno == EINTR)); \
-} while(0)
+#define RESTARTABLE(_cmd, _result)                \
+    do {                                          \
+        _result = _cmd;                           \
+    } while ((_result == -1) && (errno == EINTR))
 
 void fileDescriptorClose(JNIEnv *env, jobject this);
 
--- a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1496,6 +1496,7 @@
             CHECK_NULL_RETURN(ni_class, NULL);
         }
         ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr);
+        JNU_CHECK_EXCEPTION_RETURN(env, NULL);
         if (ni) {
             return ni;
         }
--- a/src/java.base/unix/native/libnio/ch/IOUtil.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/native/libnio/ch/IOUtil.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,7 +63,7 @@
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_IOUtil_setfdVal(JNIEnv *env, jclass clazz, jobject fdo, jint val)
 {
-    (*env)->SetIntField(env, fdo, fd_fdID, val);
+    setfdval(env, fdo, val);
 }
 
 static int
@@ -228,3 +228,10 @@
 {
     return (*env)->GetIntField(env, fdo, fd_fdID);
 }
+
+void
+setfdval(JNIEnv *env, jobject fdo, jint val) {
+    (*env)->SetIntField(env, fdo, fd_fdID, val);
+}
+
+
--- a/src/java.base/unix/native/libnio/ch/Net.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/native/libnio/ch/Net.c	Tue Mar 26 09:05:10 2019 -0400
@@ -146,9 +146,22 @@
 
 #endif  /* _AIX */
 
+static jclass isa_class;        /* java.net.InetSocketAddress */
+static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
+
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
 {
+     jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
+     CHECK_NULL(cls);
+     isa_class = (*env)->NewGlobalRef(env, cls);
+     if (isa_class == NULL) {
+         JNU_ThrowOutOfMemoryError(env, NULL);
+         return;
+     }
+     isa_ctorID = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/net/InetAddress;I)V");
+     CHECK_NULL(isa_ctorID);
+
      initInetAddressIDs(env);
 }
 
@@ -309,6 +322,51 @@
 }
 
 JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Net_accept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo,
+                           jobjectArray isaa)
+{
+    jint fd = fdval(env, fdo);
+    jint newfd;
+    SOCKETADDRESS sa;
+    socklen_t sa_len = sizeof(SOCKETADDRESS);
+    jobject remote_ia;
+    jint remote_port = 0;
+    jobject isa;
+
+    /* accept connection but ignore ECONNABORTED */
+    for (;;) {
+        newfd = accept(fd, &sa.sa, &sa_len);
+        if (newfd >= 0) {
+            break;
+        }
+        if (errno != ECONNABORTED) {
+            break;
+        }
+        /* ECONNABORTED => restart accept */
+    }
+
+    if (newfd < 0) {
+        if (errno == EAGAIN || errno == EWOULDBLOCK)
+            return IOS_UNAVAILABLE;
+        if (errno == EINTR)
+            return IOS_INTERRUPTED;
+        JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
+        return IOS_THROWN;
+    }
+
+    setfdval(env, newfdo, newfd);
+
+    remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
+    CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
+
+    isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
+    CHECK_NULL_RETURN(isa, IOS_THROWN);
+    (*env)->SetObjectArrayElement(env, isaa, 0, isa);
+
+    return 1;
+}
+
+JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
 {
     SOCKETADDRESS sa;
@@ -374,6 +432,33 @@
 }
 
 JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Net_remotePort(JNIEnv *env, jclass clazz, jobject fdo)
+{
+    SOCKETADDRESS sa;
+    socklen_t sa_len = sizeof(sa);
+
+    if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
+        handleSocketError(env, errno);
+        return IOS_THROWN;
+    }
+    return NET_GetPortFromSockaddr(&sa);
+}
+
+JNIEXPORT jobject JNICALL
+Java_sun_nio_ch_Net_remoteInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
+{
+    SOCKETADDRESS sa;
+    socklen_t sa_len = sizeof(sa);
+    int port;
+
+    if (getpeername(fdval(env, fdo), &sa.sa, &sa_len) < 0) {
+        handleSocketError(env, errno);
+        return NULL;
+    }
+    return NET_SockaddrToInetAddress(env, &sa, &port);
+}
+
+JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
                                   jboolean mayNeedConversion, jint level, jint opt)
 {
@@ -719,7 +804,7 @@
     }
 }
 
-JNIEXPORT jint JNICALL
+JNIEXPORT jboolean JNICALL
 Java_sun_nio_ch_Net_pollConnect(JNIEnv *env, jobject this, jobject fdo, jlong timeout)
 {
     jint fd = fdval(env, fdo);
@@ -743,23 +828,22 @@
         errno = 0;
         result = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n);
         if (result < 0) {
-            return handleSocketError(env, errno);
+            handleSocketError(env, errno);
+            return JNI_FALSE;
         } else if (error) {
-            return handleSocketError(env, error);
+            handleSocketError(env, error);
+            return JNI_FALSE;
         } else if ((poller.revents & POLLHUP) != 0) {
-            return handleSocketError(env, ENOTCONN);
+            handleSocketError(env, ENOTCONN);
+            return JNI_FALSE;
         }
         // connected
-        return 1;
-    } else if (result == 0) {
-        return 0;
+        return JNI_TRUE;
+    } else if (result == 0 || errno == EINTR) {
+        return JNI_FALSE;
     } else {
-        if (errno == EINTR) {
-            return IOS_INTERRUPTED;
-        } else {
-            JNU_ThrowIOExceptionWithLastError(env, "poll failed");
-            return IOS_THROWN;
-        }
+        JNU_ThrowIOExceptionWithLastError(env, "poll failed");
+        return JNI_FALSE;
     }
 }
 
@@ -830,6 +914,7 @@
             break;
         case EADDRINUSE:  /* Fall through */
         case EADDRNOTAVAIL:
+        case EACCES:
             xn = JNU_JAVANETPKG "BindException";
             break;
         default:
--- a/src/java.base/unix/native/libnio/ch/ServerSocketChannelImpl.c	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * 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
- * 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 <stdlib.h>
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#if __linux__
-#include <netinet/in.h>
-#endif
-
-#if defined(__solaris__) && !defined(_SOCKLEN_T)
-typedef size_t socklen_t;       /* New in SunOS 5.7, so need this for 5.6 */
-#endif
-
-#include "jni.h"
-#include "jni_util.h"
-#include "net_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "sun_nio_ch_ServerSocketChannelImpl.h"
-#include "nio.h"
-#include "nio_util.h"
-
-
-static jfieldID fd_fdID;        /* java.io.FileDescriptor.fd */
-static jclass isa_class;        /* java.net.InetSocketAddress */
-static jmethodID isa_ctorID;    /*   .InetSocketAddress(InetAddress, int) */
-
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv *env, jclass c)
-{
-    jclass cls;
-
-    cls = (*env)->FindClass(env, "java/io/FileDescriptor");
-    CHECK_NULL(cls);
-    fd_fdID = (*env)->GetFieldID(env, cls, "fd", "I");
-    CHECK_NULL(fd_fdID);
-
-    cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
-    CHECK_NULL(cls);
-    isa_class = (*env)->NewGlobalRef(env, cls);
-    if (isa_class == NULL) {
-        JNU_ThrowOutOfMemoryError(env, NULL);
-        return;
-    }
-    isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
-                                     "(Ljava/net/InetAddress;I)V");
-    CHECK_NULL(isa_ctorID);
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
-                                                jobject ssfdo, jobject newfdo,
-                                                jobjectArray isaa)
-{
-    jint ssfd = (*env)->GetIntField(env, ssfdo, fd_fdID);
-    jint newfd;
-    SOCKETADDRESS sa;
-    socklen_t sa_len = sizeof(SOCKETADDRESS);
-    jobject remote_ia = 0;
-    jobject isa;
-    jint remote_port = 0;
-
-    /*
-     * accept connection but ignore ECONNABORTED indicating that
-     * a connection was eagerly accepted but was reset before
-     * accept() was called.
-     */
-    for (;;) {
-        newfd = accept(ssfd, &sa.sa, &sa_len);
-        if (newfd >= 0) {
-            break;
-        }
-        if (errno != ECONNABORTED) {
-            break;
-        }
-        /* ECONNABORTED => restart accept */
-    }
-
-    if (newfd < 0) {
-        if (errno == EAGAIN || errno == EWOULDBLOCK)
-            return IOS_UNAVAILABLE;
-        if (errno == EINTR)
-            return IOS_INTERRUPTED;
-        JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
-        return IOS_THROWN;
-    }
-
-    (*env)->SetIntField(env, newfdo, fd_fdID, newfd);
-    remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
-    CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
-    isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
-    CHECK_NULL_RETURN(isa, IOS_THROWN);
-    (*env)->SetObjectArrayElement(env, isaa, 0, isa);
-    return 1;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/unix/native/libnio/ch/SocketDispatcher.c	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 <sys/types.h>
+ #include <sys/uio.h>
+ #include <unistd.h>
+
+ #include "jni.h"
+ #include "jni_util.h"
+ #include "jlong.h"
+ #include "nio.h"
+ #include "nio_util.h"
+ #include "sun_nio_ch_SocketDispatcher.h"
+
+ JNIEXPORT jint JNICALL
+ Java_sun_nio_ch_SocketDispatcher_read0(JNIEnv *env, jclass clazz,
+                                        jobject fdo, jlong address, jint len)
+ {
+     jint fd = fdval(env, fdo);
+     void *buf = (void *)jlong_to_ptr(address);
+     jint n = read(fd, buf, len);
+     if ((n == -1) && (errno == ECONNRESET || errno == EPIPE)) {
+         JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");
+         return IOS_THROWN;
+     } else {
+         return convertReturnVal(env, n, JNI_TRUE);
+     }
+ }
+
+ JNIEXPORT jlong JNICALL
+ Java_sun_nio_ch_SocketDispatcher_readv0(JNIEnv *env, jclass clazz,
+                                         jobject fdo, jlong address, jint len)
+ {
+     jint fd = fdval(env, fdo);
+     struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+     jlong n = readv(fd, iov, len);
+     if ((n == -1) && (errno == ECONNRESET || errno == EPIPE)) {
+         JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");
+         return IOS_THROWN;
+     } else {
+         return convertLongReturnVal(env, n, JNI_TRUE);
+     }
+ }
--- a/src/java.base/unix/native/libnio/ch/UnixAsynchronousServerSocketChannelImpl.c	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, 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 "sun_nio_ch_UnixAsynchronousServerSocketChannelImpl.h"
-
-extern void Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv* env,
-    jclass c);
-
-extern jint Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv* env,
-    jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa);
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs(JNIEnv* env,
-    jclass c)
-{
-    Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(env, c);
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0(JNIEnv* env,
-    jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa)
-{
-    return Java_sun_nio_ch_ServerSocketChannelImpl_accept0(env, this,
-        ssfdo, newfdo, isaa);
-}
--- a/src/java.base/unix/native/libnio/ch/nio_util.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/unix/native/libnio/ch/nio_util.h	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,6 +55,7 @@
 /* Defined in IOUtil.c */
 
 jint fdval(JNIEnv *env, jobject fdo);
+void setfdval(JNIEnv *env, jobject fdo, jint value);
 
 jint convertReturnVal(JNIEnv *env, jint n, jboolean reading);
 jlong convertLongReturnVal(JNIEnv *env, jlong n, jboolean reading);
--- a/src/java.base/windows/classes/java/io/WinNTFileSystem.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/windows/classes/java/io/WinNTFileSystem.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -328,7 +328,6 @@
                 return up + slashify(path.substring(2));
             char drive = path.charAt(0);
             String dir = getDriveDirectory(drive);
-            String np;
             if (dir != null) {
                 /* When resolving a directory-relative path that refers to a
                    drive other than the current drive, insist that the caller
@@ -641,6 +640,7 @@
     // expects the path to be null or a root component ending in a backslash
     private native int getNameMax0(String path);
 
+    @Override
     public int getNameMax(String path) {
         String s = null;
         if (path != null) {
--- a/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/windows/classes/sun/nio/ch/SocketDispatcher.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,19 +25,16 @@
 
 package sun.nio.ch;
 
-import java.io.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
 
 /**
  * Allows different platforms to call different native methods
  * for read and write operations.
  */
 
-class SocketDispatcher extends NativeDispatcher
-{
-
-    static {
-        IOUtil.load();
-    }
+class SocketDispatcher extends NativeDispatcher {
+    SocketDispatcher() { }
 
     int read(FileDescriptor fd, long address, int len) throws IOException {
         return read0(fd, address, len);
@@ -63,7 +60,8 @@
         close0(fd);
     }
 
-    //-- Native methods
+    // -- Native methods --
+
     static native int read0(FileDescriptor fd, long address, int len)
         throws IOException;
 
@@ -79,4 +77,8 @@
     static native void preClose0(FileDescriptor fd) throws IOException;
 
     static native void close0(FileDescriptor fd) throws IOException;
+
+    static {
+        IOUtil.load();
+    }
 }
--- a/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -510,8 +510,15 @@
             public String getDisplayCountry(String countryCode, Locale locale) {
                 // Retrieves the display country name by calling
                 // GetLocaleInfoEx(LOCALE_SLOCALIZEDCOUNTRYNAME).
-                return getDisplayString(locale.toLanguageTag(),
-                            DN_LOCALE_REGION, nativeDisplayLanguage+"-"+countryCode);
+                String str = getDisplayString(locale.toLanguageTag(),
+                                 DN_LOCALE_REGION,
+                                 nativeDisplayLanguage+"-"+countryCode);
+                // Hack: Windows 10 returns translated "Unknown Region (XX)"
+                // for localized XX region name. Take that as not known.
+                if (str != null && str.endsWith("("+countryCode+")")) {
+                    return null;
+                }
+                return str;
             }
 
             @Override
--- a/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/windows/native/libjava/HostLocaleProviderAdapter_md.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -168,11 +168,6 @@
     }
 };
 
-
-// Localized region name for unknown regions (Windows 10)
-#define UNKNOWN_REGION  L"Unknown Region ("
-#define UNKNOWN_REGION_SIZE wcslen(UNKNOWN_REGION)
-
 /*
  * Class:     sun_util_locale_provider_HostLocaleProviderAdapterImpl
  * Method:    initialize
@@ -755,15 +750,10 @@
     (*env)->ReleaseStringChars(env, jStr, pjChar);
 
     if (got) {
-        // Hack: Windows 10 returns "Unknown Region (XX)" for localized XX region name.
-        // Take that as not known.
-        if (type != sun_util_locale_provider_HostLocaleProviderAdapterImpl_DN_LOCALE_REGION ||
-            wcsncmp(UNKNOWN_REGION, buf, UNKNOWN_REGION_SIZE) != 0) {
-            return (*env)->NewString(env, buf, (jsize)wcslen(buf));
-        }
+        return (*env)->NewString(env, buf, (jsize)wcslen(buf));
+    } else {
+        return NULL;
     }
-
-    return NULL;
 }
 
 int getLocaleInfoWrapper(const jchar *langtag, LCTYPE type, LPWSTR data, int buflen) {
--- a/src/java.base/windows/native/libnio/ch/IOUtil.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/windows/native/libnio/ch/IOUtil.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,7 +119,7 @@
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_IOUtil_setfdVal(JNIEnv *env, jclass clazz, jobject fdo, jint val)
 {
-    (*env)->SetIntField(env, fdo, fd_fdID, val);
+    setfdval(env, fdo, val);
 }
 
 
@@ -198,6 +198,12 @@
     return (*env)->GetIntField(env, fdo, fd_fdID);
 }
 
+void
+setfdval(JNIEnv *env, jobject fdo, jint val)
+{
+    (*env)->SetIntField(env, fdo, fd_fdID, val);
+}
+
 jlong
 handleval(JNIEnv *env, jobject fdo)
 {
--- a/src/java.base/windows/native/libnio/ch/Net.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/windows/native/libnio/ch/Net.c	Tue Mar 26 09:05:10 2019 -0400
@@ -83,10 +83,23 @@
     return IOS_THROWN;
 }
 
+static jclass isa_class;        /* java.net.InetSocketAddress */
+static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
+
 JNIEXPORT void JNICALL
 Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz)
 {
-    initInetAddressIDs(env);
+     jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
+     CHECK_NULL(cls);
+     isa_class = (*env)->NewGlobalRef(env, cls);
+     if (isa_class == NULL) {
+         JNU_ThrowOutOfMemoryError(env, NULL);
+         return;
+     }
+     isa_ctorID = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/net/InetAddress;I)V");
+     CHECK_NULL(isa_ctorID);
+
+     initInetAddressIDs(env);
 }
 
 JNIEXPORT jboolean JNICALL
@@ -192,7 +205,6 @@
     }
 }
 
-
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6, jobject fdo,
                              jobject iao, jint port)
@@ -226,6 +238,42 @@
 }
 
 JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Net_accept(JNIEnv *env, jclass clazz, jobject fdo, jobject newfdo,
+                           jobjectArray isaa)
+{
+    jint fd = fdval(env,fdo);
+    jint newfd;
+    SOCKETADDRESS sa;
+    int addrlen = sizeof(sa);
+    jobject remote_ia;
+    jint remote_port = 0;
+    jobject isa;
+
+    memset((char *)&sa, 0, sizeof(sa));
+    newfd = (jint) accept(fd, &sa.sa, &addrlen);
+    if (newfd == INVALID_SOCKET) {
+        int theErr = (jint)WSAGetLastError();
+        if (theErr == WSAEWOULDBLOCK) {
+            return IOS_UNAVAILABLE;
+        }
+        JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
+        return IOS_THROWN;
+    }
+
+    SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
+    setfdval(env, newfdo, newfd);
+
+    remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
+    CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
+
+    isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
+    CHECK_NULL_RETURN(isa, IOS_THROWN);
+    (*env)->SetObjectArrayElement(env, isaa, 0, isa);
+
+    return 1;
+}
+
+JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
 {
     SOCKETADDRESS sa;
@@ -612,7 +660,7 @@
     return rv;
 }
 
-JNIEXPORT jint JNICALL
+JNIEXPORT jboolean JNICALL
 Java_sun_nio_ch_Net_pollConnect(JNIEnv* env, jclass this, jobject fdo, jlong timeout)
 {
     int optError = 0;
@@ -636,13 +684,13 @@
 
     if (result == SOCKET_ERROR) {
         handleSocketError(env, WSAGetLastError());
-        return IOS_THROWN;
+        return JNI_FALSE;
     } else if (result == 0) {
-        return 0;
+        return JNI_FALSE;
     } else {
         // connection established if writable and no error to check
         if (FD_ISSET(fd, &wr) && !FD_ISSET(fd, &ex)) {
-            return 1;
+            return JNI_TRUE;
         }
         result = getsockopt((SOCKET)fd,
                             SOL_SOCKET,
@@ -651,17 +699,13 @@
                             &n);
         if (result == SOCKET_ERROR) {
             int lastError = WSAGetLastError();
-            if (lastError == WSAEINPROGRESS) {
-                return IOS_UNAVAILABLE;
+            if (lastError != WSAEINPROGRESS) {
+                NET_ThrowNew(env, lastError, "getsockopt");
             }
-            NET_ThrowNew(env, lastError, "getsockopt");
-            return IOS_THROWN;
+        } else if (optError != NO_ERROR) {
+            handleSocketError(env, optError);
         }
-        if (optError != NO_ERROR) {
-            handleSocketError(env, optError);
-            return IOS_THROWN;
-        }
-        return 0;
+        return JNI_FALSE;
     }
 }
 
--- a/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2000, 2010, 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 <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-
-#include "nio.h"
-#include "nio_util.h"
-#include "net_util.h"
-
-#include "sun_nio_ch_ServerSocketChannelImpl.h"
-
-
-static jfieldID fd_fdID;        /* java.io.FileDescriptor.fd */
-static jclass isa_class;        /* java.net.InetSocketAddress */
-static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
-
-
-/**************************************************************
- * static method to store field IDs in initializers
- */
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv *env, jclass cls)
-{
-    cls = (*env)->FindClass(env, "java/io/FileDescriptor");
-    CHECK_NULL(cls);
-    fd_fdID = (*env)->GetFieldID(env, cls, "fd", "I");
-    CHECK_NULL(fd_fdID);
-
-    cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
-    CHECK_NULL(cls);
-    isa_class = (*env)->NewGlobalRef(env, cls);
-    if (isa_class == NULL) {
-        JNU_ThrowOutOfMemoryError(env, NULL);
-        return;
-    }
-    isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
-                                     "(Ljava/net/InetAddress;I)V");
-    CHECK_NULL(isa_ctorID);
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_ServerSocketChannelImpl_listen(JNIEnv *env, jclass cl,
-                                               jobject fdo, jint backlog)
-{
-    if (listen(fdval(env,fdo), backlog) == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "listen");
-    }
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
-                                                jobject ssfdo, jobject newfdo,
-                                                jobjectArray isaa)
-{
-    jint ssfd = (*env)->GetIntField(env, ssfdo, fd_fdID);
-    jint newfd;
-    SOCKETADDRESS sa;
-    jobject remote_ia;
-    int remote_port;
-    jobject isa;
-    int addrlen = sizeof(sa);
-
-    memset((char *)&sa, 0, sizeof(sa));
-    newfd = (jint)accept(ssfd, &sa.sa, &addrlen);
-    if (newfd == INVALID_SOCKET) {
-        int theErr = (jint)WSAGetLastError();
-        if (theErr == WSAEWOULDBLOCK) {
-            return IOS_UNAVAILABLE;
-        }
-        JNU_ThrowIOExceptionWithLastError(env, "Accept failed");
-        return IOS_THROWN;
-    }
-
-    SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
-    (*env)->SetIntField(env, newfdo, fd_fdID, newfd);
-    remote_ia = NET_SockaddrToInetAddress(env, &sa, (int *)&remote_port);
-    CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
-
-    isa = (*env)->NewObject(env, isa_class, isa_ctorID, remote_ia, remote_port);
-    CHECK_NULL_RETURN(isa, IOS_THROWN);
-    (*env)->SetObjectArrayElement(env, isaa, 0, isa);
-    return 1;
-}
--- a/src/java.base/windows/native/libnio/ch/SocketDispatcher.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/windows/native/libnio/ch/SocketDispatcher.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,7 +72,11 @@
         if (theErr == WSAEWOULDBLOCK) {
             return IOS_UNAVAILABLE;
         }
-        JNU_ThrowIOExceptionWithLastError(env, "Read failed");
+        if (theErr == WSAECONNRESET) {
+            JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "Read failed");
+        }
         return IOS_THROWN;
     }
 
@@ -128,7 +132,11 @@
         if (theErr == WSAEWOULDBLOCK) {
             return IOS_UNAVAILABLE;
         }
-        JNU_ThrowIOExceptionWithLastError(env, "Vector read failed");
+        if (theErr == WSAECONNRESET) {
+            JNU_ThrowByName(env, "sun/net/ConnectionResetException", "Connection reset");
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "Vector read failed");
+        }
         return IOS_THROWN;
     }
 
@@ -174,7 +182,11 @@
                if (theErr == WSAEWOULDBLOCK) {
                    return IOS_UNAVAILABLE;
                }
-               JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+               if (theErr == WSAECONNRESET) {
+                   JNU_ThrowIOException(env, "Connection reset by peer");
+               } else {
+                   JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+               }
                return IOS_THROWN;
             }
         }
@@ -256,7 +268,11 @@
         if (theErr == WSAEWOULDBLOCK) {
             return IOS_UNAVAILABLE;
         }
-        JNU_ThrowIOExceptionWithLastError(env, "Vector write failed");
+        if (theErr == WSAECONNRESET) {
+            JNU_ThrowIOException(env, "Connection reset by peer");
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "Vector write failed");
+        }
         return IOS_THROWN;
     }
 
--- a/src/java.base/windows/native/libnio/ch/nio_util.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.base/windows/native/libnio/ch/nio_util.h	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
 #define MAX_BUFFER_SIZE             ((128*1024)-1)
 
 jint fdval(JNIEnv *env, jobject fdo);
+void setfdval(JNIEnv *env, jobject fdo, jint val);
 jlong handleval(JNIEnv *env, jobject fdo);
 jint convertReturnVal(JNIEnv *env, jint n, jboolean r);
 jlong convertLongReturnVal(JNIEnv *env, jlong n, jboolean r);
--- a/src/java.compiler/share/classes/javax/annotation/processing/Generated.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.compiler/share/classes/javax/annotation/processing/Generated.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
  * It can also be used to differentiate user written code from generated code in
  * a single file.
  *
- * <h3>Examples:</h3>
+ * <h2>Examples:</h2>
  * <pre>
  *   &#064;Generated("com.example.Generator")
  * </pre>
--- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@
      *   9: modules, small cleanups to 1.7 and 1.8 changes
      *  10: local-variable type inference (var)
      *  11: local-variable syntax for lambda parameters
-     *  12: TBD
+     *  12: no changes (switch expressions in preview)
      *  13: TBD
      */
 
@@ -208,38 +208,40 @@
 
     private static final SourceVersion latestSupported = getLatestSupported();
 
+    /*
+     * The integer version to enum constant mapping implemented by
+     * this method assumes the JEP 322: "Time-Based Release
+     * Versioning" scheme is in effect. This scheme began in JDK
+     * 10. If the JDK versioning scheme is revised, this method may
+     * need to be updated accordingly.
+     */
     private static SourceVersion getLatestSupported() {
-        try {
-            String specVersion = System.getProperty("java.specification.version");
-
-            switch (specVersion) {
-                case "13":
-                    return RELEASE_13;
-                case "12":
-                    return RELEASE_12;
-                case "11":
-                    return RELEASE_11;
-                case "10":
-                    return RELEASE_10;
-                case "9":
-                    return RELEASE_9;
-                case "1.8":
-                    return RELEASE_8;
-                case "1.7":
-                    return RELEASE_7;
-                case "1.6":
-                    return RELEASE_6;
-            }
-        } catch (SecurityException se) {}
-
-        return RELEASE_5;
+        int intVersion = Runtime.version().feature();
+        return (intVersion >= 11) ?
+            valueOf("RELEASE_" + Math.min(13, intVersion)):
+            RELEASE_10;
     }
 
     /**
      * Returns the latest source version fully supported by the
-     * current execution environment.  {@code RELEASE_5} or later must
+     * current execution environment.  {@code RELEASE_9} or later must
      * be returned.
      *
+     * @apiNote This method is included alongside {@link latest} to
+     * allow identification of situations where the language model API
+     * is running on a platform version different than the latest
+     * version modeled by the API. One way that sort of situation can
+     * occur is if an IDE or similar tool is using the API to model
+     * source version <i>N</i> while running on platform version
+     * (<i>N</i>&nbsp;-&nbsp;1). Running in this configuration is
+     * supported by the API. Running an API on platform versions
+     * earlier than (<i>N</i>&nbsp;-&nbsp;1) or later than <i>N</i>
+     * may or may not work as an implementation detail. If an
+     * annotation processor was generating code to run under the
+     * current execution environment, the processor should only use
+     * platform features up to the {@code latestSupported} release,
+     * which may be earlier than the {@code latest} release.
+     *
      * @return the latest source version that is fully supported
      */
     public static SourceVersion latestSupported() {
--- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 import java.awt.KeyboardFocusManager;
 import java.awt.Point;
 import java.awt.Window;
+import java.awt.event.KeyEvent;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.lang.reflect.InvocationTargetException;
@@ -54,7 +55,9 @@
 import javax.swing.JComponent;
 import javax.swing.JEditorPane;
 import javax.swing.JLabel;
+import javax.swing.JMenuItem;
 import javax.swing.JTextArea;
+import javax.swing.KeyStroke;
 
 import sun.awt.AWTAccessor;
 import sun.lwawt.LWWindowPeer;
@@ -355,6 +358,10 @@
                 if (accessibleName == null) {
                     return ac.getAccessibleDescription();
                 }
+                final String acceleratorText = getAcceleratorText(ac);
+                if (!acceleratorText.isEmpty()) {
+                    return accessibleName +' '+ acceleratorText;
+                }
                 return accessibleName;
             }
         }, c);
@@ -374,6 +381,41 @@
         }, c);
     }
 
+    /*
+     * Returns the JMenuItem accelerator. Implementation of this method is based
+     * on AccessBridge.getAccelerator(AccessibleContext) to access the KeyStroke
+     * and on AquaMenuPainter.paintMenuItem() to convert it to string.
+     */
+    @SuppressWarnings("deprecation")
+    private static String getAcceleratorText(AccessibleContext ac) {
+        String accText = "";
+        Accessible parent = ac.getAccessibleParent();
+        if (parent != null) {
+            // workaround for getAccessibleKeyBinding not returning the
+            // JMenuItem accelerator
+            int indexInParent = ac.getAccessibleIndexInParent();
+            Accessible child = parent.getAccessibleContext()
+                                     .getAccessibleChild(indexInParent);
+            if (child instanceof JMenuItem) {
+                JMenuItem menuItem = (JMenuItem) child;
+                KeyStroke keyStroke = menuItem.getAccelerator();
+                if (keyStroke != null) {
+                    int modifiers = keyStroke.getModifiers();
+                    if (modifiers > 0) {
+                        accText = KeyEvent.getKeyModifiersText(modifiers);
+                    }
+                    int keyCode = keyStroke.getKeyCode();
+                    if (keyCode != 0) {
+                        accText += KeyEvent.getKeyText(keyCode);
+                    } else {
+                        accText += keyStroke.getKeyChar();
+                    }
+                }
+            }
+        }
+        return accText;
+    }
+
     public static String getAccessibleDescription(final Accessible a, final Component c) {
         if (a == null) return null;
 
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java	Tue Mar 26 09:05:10 2019 -0400
@@ -3322,11 +3322,11 @@
     private class TabbedPaneScrollLayout extends TabbedPaneLayout {
 
         protected int preferredTabAreaHeight(int tabPlacement, int width) {
-            return calculateMaxTabHeight(tabPlacement);
+            return calculateTabAreaHeight(tabPlacement, 1, calculateMaxTabHeight(tabPlacement));
         }
 
         protected int preferredTabAreaWidth(int tabPlacement, int height) {
-            return calculateMaxTabWidth(tabPlacement);
+            return calculateTabAreaWidth(tabPlacement, 1, calculateMaxTabWidth(tabPlacement));
         }
 
         @SuppressWarnings("deprecation")
--- a/src/java.desktop/share/classes/javax/swing/text/html/ImageView.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/classes/javax/swing/text/html/ImageView.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 
 import java.awt.Rectangle;
 import java.awt.Image;
+import java.awt.Dimension;
 import java.awt.Container;
 import java.awt.Color;
 import java.awt.Shape;
@@ -782,6 +783,20 @@
                 newState |= HEIGHT_FLAG;
             }
 
+            /*
+            If synchronous loading flag is set, then make sure that the image is
+            scaled appropriately.
+            Otherwise, the ImageHandler::imageUpdate takes care of scaling the image
+            appropriately.
+            */
+            if (getLoadsSynchronously()) {
+                Dimension d = adjustWidthHeight(image.getWidth(imageObserver),
+                                                image.getHeight(imageObserver));
+                newWidth = d.width;
+                newHeight = d.height;
+                newState |= (WIDTH_FLAG | HEIGHT_FLAG);
+            }
+
             // Make sure the image starts loading:
             if ((newState & (WIDTH_FLAG | HEIGHT_FLAG)) != 0) {
                 Toolkit.getDefaultToolkit().prepareImage(newImage, newWidth,
@@ -885,6 +900,40 @@
         }
     }
 
+    private Dimension adjustWidthHeight(int newWidth, int newHeight) {
+        Dimension d = new Dimension();
+        double proportion = 0.0;
+        final int specifiedWidth = getIntAttr(HTML.Attribute.WIDTH, -1);
+        final int specifiedHeight = getIntAttr(HTML.Attribute.HEIGHT, -1);
+        /**
+         * If either of the attributes are not specified, then calculate the
+         * proportion for the specified dimension wrt actual value, and then
+         * apply the same proportion to the unspecified dimension as well,
+         * so that the aspect ratio of the image is maintained.
+         */
+        if (specifiedWidth != -1 && specifiedHeight != -1) {
+            newWidth = specifiedWidth;
+            newHeight = specifiedHeight;
+        } else if (specifiedWidth != -1 ^ specifiedHeight != -1) {
+            if (specifiedWidth <= 0) {
+                proportion = specifiedHeight / ((double)newHeight);
+                newWidth = (int)(proportion * newWidth);
+                newHeight = specifiedHeight;
+            }
+
+            if (specifiedHeight <= 0) {
+                proportion = specifiedWidth / ((double)newWidth);
+                newHeight = (int)(proportion * newHeight);
+                newWidth = specifiedWidth;
+            }
+        }
+
+        d.width = newWidth;
+        d.height = newHeight;
+
+        return d;
+    }
+
     /**
      * ImageHandler implements the ImageObserver to correctly update the
      * display as new parts of the image become available.
@@ -950,27 +999,10 @@
                  */
                 if (((flags & ImageObserver.HEIGHT) != 0) &&
                     ((flags & ImageObserver.WIDTH) != 0)) {
-                    double proportion = 0.0;
-                    final int specifiedWidth = getIntAttr(HTML.Attribute.WIDTH, -1);
-                    final int specifiedHeight = getIntAttr(HTML.Attribute.HEIGHT, -1);
-                    /**
-                     * If either of the attributes are not specified, then calculate the
-                     * proportion for the specified dimension wrt actual value, and then
-                     * apply the same proportion to the unspecified dimension as well,
-                     * so that the aspect ratio of the image is maintained.
-                     */
-                    if (specifiedWidth != -1 ^ specifiedHeight != -1) {
-                        if (specifiedWidth <= 0) {
-                            proportion = specifiedHeight / ((double)newHeight);
-                            newWidth = (int)(proportion * newWidth);
-                        }
-
-                        if (specifiedHeight <= 0) {
-                            proportion = specifiedWidth / ((double)newWidth);
-                            newHeight = (int)(proportion * newHeight);
-                        }
+                        Dimension d = adjustWidthHeight(newWidth, newHeight);
+                        newWidth = d.width;
+                        newHeight = d.height;
                         changed |= 3;
-                    }
                 }
                 synchronized(ImageView.this) {
                     if ((changed & 1) == 1 && (state & HEIGHT_FLAG) == 0) {
--- a/src/java.desktop/share/legal/harfbuzz.md	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/legal/harfbuzz.md	Tue Mar 26 09:05:10 2019 -0400
@@ -1,4 +1,4 @@
-## Harfbuzz v1.8.2
+## Harfbuzz v2.3.1
 
 ### Harfbuzz License
 
--- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -405,10 +405,18 @@
     return errCode;
 }
 
-/* ftsynth.c uses (0x10000, 0x06000, 0x0, 0x10000) matrix to get oblique
-   outline.  Therefore x coordinate will change by 0x06000*y.
-   Note that y coordinate does not change. */
-#define OBLIQUE_MODIFIER(y)  (context->doItalize ? ((y)*6/16) : 0)
+/* ftsynth.c uses (0x10000, 0x0366A, 0x0, 0x10000) matrix to get oblique
+   outline.  Therefore x coordinate will change by 0x0366A*y.
+   Note that y coordinate does not change. These values are based on
+   libfreetype version 2.9.1. */
+#define OBLIQUE_MODIFIER(y)  (context->doItalize ? ((y)*0x366A/0x10000) : 0)
+
+/* FT_GlyphSlot_Embolden (ftsynth.c) uses FT_MulFix(units_per_EM, y_scale) / 24
+ * strength value when glyph format is FT_GLYPH_FORMAT_OUTLINE. This value has
+ * been taken from libfreetype version 2.6 and remain valid at least up to
+ * 2.9.1. */
+#define BOLD_MODIFIER(units_per_EM, y_scale) \
+    (context->doBold ? FT_MulFix(units_per_EM, y_scale) / 24 : 0)
 
 /*
  * Class:     sun_font_FreetypeFontScaler
@@ -495,7 +503,9 @@
     /* max advance */
     mx = (jfloat) FT26Dot6ToFloat(
                      scalerInfo->face->size->metrics.max_advance +
-                     OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height));
+                     OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height) +
+                     BOLD_MODIFIER(scalerInfo->face->units_per_EM,
+                             scalerInfo->face->size->metrics.y_scale));
     my = 0;
 
     metrics = (*env)->NewObject(env,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-fdsc-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_FDSC_TABLE_HH
+#define HB_AAT_FDSC_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-open-type.hh"
+
+/*
+ * fdsc -- Font descriptors
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fdsc.html
+ */
+#define HB_AAT_TAG_fdsc HB_TAG('f','d','s','c')
+
+
+namespace AAT {
+
+
+struct FontDescriptor
+{
+  bool has_data () const { return tag; }
+
+  int cmp (hb_tag_t a) const { return tag.cmp (a); }
+
+  float get_value () const { return u.value.to_float (); }
+
+  enum non_alphabetic_value_t {
+    Alphabetic          = 0,
+    Dingbats            = 1,
+    PiCharacters        = 2,
+    Fleurons            = 3,
+    DecorativeBorders   = 4,
+    InternationalSymbols= 5,
+    MathSymbols         = 6
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  Tag           tag;            /* The 4-byte table tag name. */
+  union {
+  Fixed         value;          /* The value for the descriptor tag. */
+  HBUINT32      nalfType;       /* If the tag is `nalf`, see non_alphabetic_value_t */
+  } u;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct fdsc
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_fdsc;
+
+  enum {
+    Weight       = HB_TAG ('w','g','h','t'),
+                                /* Percent weight relative to regular weight.
+                                 * (defaul value: 1.0) */
+    Width        = HB_TAG ('w','d','t','h'),
+                                /* Percent width relative to regular width.
+                                 * (default value: 1.0) */
+    Slant        = HB_TAG ('s','l','n','t'),
+                                /* Angle of slant in degrees, where positive
+                                 * is clockwise from straight up.
+                                 * (default value: 0.0) */
+    OpticalSize  = HB_TAG ('o','p','s','z'),
+                                /* Point size the font was designed for.
+                                 * (default value: 12.0) */
+    NonAlphabetic= HB_TAG ('n','a','l','f')
+                                /* These values are treated as integers,
+                                 * not fixed32s. 0 means alphabetic, and greater
+                                 * integers mean the font is non-alphabetic (e.g. symbols).
+                                 * (default value: 0) */
+  };
+
+  const FontDescriptor &get_descriptor (hb_tag_t style) const
+  { return descriptors.lsearch (style); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  descriptors.sanitize (c));
+  }
+
+  protected:
+  Fixed         version;        /* Version number of the font descriptors
+                                 * table (0x00010000 for the current version). */
+  LArrayOf<FontDescriptor>
+                descriptors;    /* List of tagged-coordinate pairs style descriptors
+                                 * that will be included to characterize this font.
+                                 * Each descriptor consists of a <tag, value> pair.
+                                 * These pairs are located in the gxFontDescriptor
+                                 * array that follows. */
+  public:
+  DEFINE_SIZE_ARRAY (8, descriptors);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_FDSC_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-ankr-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_LAYOUT_ANKR_TABLE_HH
+#define HB_AAT_LAYOUT_ANKR_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+
+/*
+ * ankr -- Anchor Point
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ankr.html
+ */
+#define HB_AAT_TAG_ankr HB_TAG('a','n','k','r')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+struct Anchor
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  FWORD         xCoordinate;
+  FWORD         yCoordinate;
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+typedef LArrayOf<Anchor> GlyphAnchors;
+
+struct ankr
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_ankr;
+
+  const Anchor &get_anchor (hb_codepoint_t glyph_id,
+                            unsigned int i,
+                            unsigned int num_glyphs) const
+  {
+    const NNOffsetTo<GlyphAnchors> *offset = (this+lookupTable).get_value (glyph_id, num_glyphs);
+    if (!offset)
+      return Null(Anchor);
+    const GlyphAnchors &anchors = &(this+anchorData) + *offset;
+    return anchors[i];
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version == 0 &&
+                          lookupTable.sanitize (c, this, &(this+anchorData))));
+  }
+
+  protected:
+  HBUINT16      version;        /* Version number (set to zero) */
+  HBUINT16      flags;          /* Flags (currently unused; set to zero) */
+  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors> > >
+                lookupTable;    /* Offset to the table's lookup table */
+  LNNOffsetTo<HBUINT8>
+                anchorData;     /* Offset to the glyph data table */
+
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_ANKR_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-bsln-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,158 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_LAYOUT_BSLN_TABLE_HH
+#define HB_AAT_LAYOUT_BSLN_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+
+/*
+ * bsln -- Baseline
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bsln.html
+ */
+#define HB_AAT_TAG_bsln HB_TAG('b','s','l','n')
+
+
+namespace AAT {
+
+
+struct BaselineTableFormat0Part
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  // Roman, Ideographic centered, Ideographic low, Hanging and Math
+  // are the default defined ones, but any other maybe accessed also.
+  HBINT16       deltas[32];     /* These are the FUnit distance deltas from
+                                 * the font's natural baseline to the other
+                                 * baselines used in the font. */
+  public:
+  DEFINE_SIZE_STATIC (64);
+};
+
+struct BaselineTableFormat1Part
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          lookupTable.sanitize (c)));
+  }
+
+  protected:
+  HBINT16       deltas[32];     /* ditto */
+  Lookup<HBUINT16>
+                lookupTable;    /* Lookup table that maps glyphs to their
+                                 * baseline values. */
+  public:
+  DEFINE_SIZE_MIN (66);
+};
+
+struct BaselineTableFormat2Part
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  GlyphID       stdGlyph;       /* The specific glyph index number in this
+                                 * font that is used to set the baseline values.
+                                 * This is the standard glyph.
+                                 * This glyph must contain a set of control points
+                                 * (whose numbers are contained in the ctlPoints field)
+                                 * that are used to determine baseline distances. */
+  HBUINT16      ctlPoints[32];  /* Set of control point numbers,
+                                 * associated with the standard glyph.
+                                 * A value of 0xFFFF means there is no corresponding
+                                 * control point in the standard glyph. */
+  public:
+  DEFINE_SIZE_STATIC (66);
+};
+
+struct BaselineTableFormat3Part
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && lookupTable.sanitize (c));
+  }
+
+  protected:
+  GlyphID       stdGlyph;       /* ditto */
+  HBUINT16      ctlPoints[32];  /* ditto */
+  Lookup<HBUINT16>
+                lookupTable;    /* Lookup table that maps glyphs to their
+                                 * baseline values. */
+  public:
+  DEFINE_SIZE_MIN (68);
+};
+
+struct bsln
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_bsln;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this) && defaultBaseline < 32)))
+      return_trace (false);
+
+    switch (format)
+    {
+    case 0: return_trace (parts.format0.sanitize (c));
+    case 1: return_trace (parts.format1.sanitize (c));
+    case 2: return_trace (parts.format2.sanitize (c));
+    case 3: return_trace (parts.format3.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version number of the Baseline table. */
+  HBUINT16      format;         /* Format of the baseline table. Only one baseline
+                                 * format may be selected for the font. */
+  HBUINT16      defaultBaseline;/* Default baseline value for all glyphs.
+                                 * This value can be from 0 through 31. */
+  union {
+  // Distance-Based Formats
+  BaselineTableFormat0Part      format0;
+  BaselineTableFormat1Part      format1;
+  // Control Point-based Formats
+  BaselineTableFormat2Part      format2;
+  BaselineTableFormat3Part      format3;
+  } parts;
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_BSLN_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-common.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,845 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_COMMON_HH
+#define HB_AAT_LAYOUT_COMMON_HH
+
+#include "hb-aat-layout.hh"
+#include "hb-open-type.hh"
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+/*
+ * Lookup Table
+ */
+
+template <typename T> struct Lookup;
+
+template <typename T>
+struct LookupFormat0
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    if (unlikely (glyph_id >= num_glyphs)) return nullptr;
+    return &arrayZ[glyph_id];
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (arrayZ.sanitize (c, c->get_num_glyphs (), base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 0 */
+  UnsizedArrayOf<T>
+                arrayZ;         /* Array of lookup values, indexed by glyph index. */
+  public:
+  DEFINE_SIZE_UNBOUNDED (2);
+};
+
+
+template <typename T>
+struct LookupSegmentSingle
+{
+  static constexpr unsigned TerminationWordCount = 2u;
+
+  int cmp (hb_codepoint_t g) const
+  { return g < first ? -1 : g <= last ? 0 : +1 ; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c, base));
+  }
+
+  GlyphID       last;           /* Last GlyphID in this segment */
+  GlyphID       first;          /* First GlyphID in this segment */
+  T             value;          /* The lookup value (only one) */
+  public:
+  DEFINE_SIZE_STATIC (4 + T::static_size);
+};
+
+template <typename T>
+struct LookupFormat2
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
+    return v ? &v->value : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 2 */
+  VarSizedBinSearchArrayOf<LookupSegmentSingle<T> >
+                segments;       /* The actual segments. These must already be sorted,
+                                 * according to the first word in each one (the last
+                                 * glyph in each segment). */
+  public:
+  DEFINE_SIZE_ARRAY (8, segments);
+};
+
+template <typename T>
+struct LookupSegmentArray
+{
+  static constexpr unsigned TerminationWordCount = 2u;
+
+  const T* get_value (hb_codepoint_t glyph_id, const void *base) const
+  {
+    return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
+  }
+
+  int cmp (hb_codepoint_t g) const
+  { return g < first ? -1 : g <= last ? 0 : +1; }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  first <= last &&
+                  valuesZ.sanitize (c, base, last - first + 1));
+  }
+  template <typename T2>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T2 user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  first <= last &&
+                  valuesZ.sanitize (c, base, last - first + 1, user_data));
+  }
+
+  GlyphID       last;           /* Last GlyphID in this segment */
+  GlyphID       first;          /* First GlyphID in this segment */
+  NNOffsetTo<UnsizedArrayOf<T> >
+                valuesZ;        /* A 16-bit offset from the start of
+                                 * the table to the data. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename T>
+struct LookupFormat4
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
+    return v ? v->get_value (glyph_id, this) : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, this));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (segments.sanitize (c, this, base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 4 */
+  VarSizedBinSearchArrayOf<LookupSegmentArray<T> >
+                segments;       /* The actual segments. These must already be sorted,
+                                 * according to the first word in each one (the last
+                                 * glyph in each segment). */
+  public:
+  DEFINE_SIZE_ARRAY (8, segments);
+};
+
+template <typename T>
+struct LookupSingle
+{
+  static constexpr unsigned TerminationWordCount = 1u;
+
+  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && value.sanitize (c, base));
+  }
+
+  GlyphID       glyph;          /* Last GlyphID */
+  T             value;          /* The lookup value (only one) */
+  public:
+  DEFINE_SIZE_STATIC (2 + T::static_size);
+};
+
+template <typename T>
+struct LookupFormat6
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    const LookupSingle<T> *v = entries.bsearch (glyph_id);
+    return v ? &v->value : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (entries.sanitize (c));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (entries.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 6 */
+  VarSizedBinSearchArrayOf<LookupSingle<T> >
+                entries;        /* The actual entries, sorted by glyph index. */
+  public:
+  DEFINE_SIZE_ARRAY (8, entries);
+};
+
+template <typename T>
+struct LookupFormat8
+{
+  friend struct Lookup<T>;
+
+  private:
+  const T* get_value (hb_codepoint_t glyph_id) const
+  {
+    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ?
+           &valueArrayZ[glyph_id - firstGlyph] : nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount, base));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 8 */
+  GlyphID       firstGlyph;     /* First glyph index included in the trimmed array. */
+  HBUINT16      glyphCount;     /* Total number of glyphs (equivalent to the last
+                                 * glyph minus the value of firstGlyph plus 1). */
+  UnsizedArrayOf<T>
+                valueArrayZ;    /* The lookup values (indexed by the glyph index
+                                 * minus the value of firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (6, valueArrayZ);
+};
+
+template <typename T>
+struct LookupFormat10
+{
+  friend struct Lookup<T>;
+
+  private:
+  const typename T::type get_value_or_null (hb_codepoint_t glyph_id) const
+  {
+    if (!(firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount))
+      return Null(T);
+
+    const HBUINT8 *p = &valueArrayZ[(glyph_id - firstGlyph) * valueSize];
+
+    unsigned int v = 0;
+    unsigned int count = valueSize;
+    for (unsigned int i = 0; i < count; i++)
+      v = (v << 8) | *p++;
+
+    return v;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  valueSize <= 4 &&
+                  valueArrayZ.sanitize (c, glyphCount * valueSize));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 8 */
+  HBUINT16      valueSize;      /* Byte size of each value. */
+  GlyphID       firstGlyph;     /* First glyph index included in the trimmed array. */
+  HBUINT16      glyphCount;     /* Total number of glyphs (equivalent to the last
+                                 * glyph minus the value of firstGlyph plus 1). */
+  UnsizedArrayOf<HBUINT8>
+                valueArrayZ;    /* The lookup values (indexed by the glyph index
+                                 * minus the value of firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (8, valueArrayZ);
+};
+
+template <typename T>
+struct Lookup
+{
+  const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    switch (u.format) {
+    case 0: return u.format0.get_value (glyph_id, num_glyphs);
+    case 2: return u.format2.get_value (glyph_id);
+    case 4: return u.format4.get_value (glyph_id);
+    case 6: return u.format6.get_value (glyph_id);
+    case 8: return u.format8.get_value (glyph_id);
+    default:return nullptr;
+    }
+  }
+
+  const typename T::type get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    switch (u.format) {
+      /* Format 10 cannot return a pointer. */
+      case 10: return u.format10.get_value_or_null (glyph_id);
+      default:
+      const T *v = get_value (glyph_id, num_glyphs);
+      return v ? *v : Null(T);
+    }
+  }
+
+  typename T::type get_class (hb_codepoint_t glyph_id,
+                              unsigned int num_glyphs,
+                              unsigned int outOfRange) const
+  {
+    const T *v = get_value (glyph_id, num_glyphs);
+    return v ? *v : outOfRange;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 0: return_trace (u.format0.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    case 4: return_trace (u.format4.sanitize (c));
+    case 6: return_trace (u.format6.sanitize (c));
+    case 8: return_trace (u.format8.sanitize (c));
+    case 10: return_trace (u.format10.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 0: return_trace (u.format0.sanitize (c, base));
+    case 2: return_trace (u.format2.sanitize (c, base));
+    case 4: return_trace (u.format4.sanitize (c, base));
+    case 6: return_trace (u.format6.sanitize (c, base));
+    case 8: return_trace (u.format8.sanitize (c, base));
+    case 10: return_trace (false); /* We don't support format10 here currently. */
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  LookupFormat0<T>      format0;
+  LookupFormat2<T>      format2;
+  LookupFormat4<T>      format4;
+  LookupFormat6<T>      format6;
+  LookupFormat8<T>      format8;
+  LookupFormat10<T>     format10;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+/* Lookup 0 has unbounded size (dependant on num_glyphs).  So we need to defined
+ * special NULL objects for Lookup<> objects, but since it's template our macros
+ * don't work.  So we have to hand-code them here.  UGLY. */
+} /* Close namespace. */
+/* Ugly hand-coded null objects for template Lookup<> :(. */
+extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
+template <>
+/*static*/ inline const AAT::Lookup<OT::HBUINT16>& Null<AAT::Lookup<OT::HBUINT16> > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT16> *> (_hb_Null_AAT_Lookup); }
+template <>
+/*static*/ inline const AAT::Lookup<OT::HBUINT32>& Null<AAT::Lookup<OT::HBUINT32> > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT32> *> (_hb_Null_AAT_Lookup); }
+template <>
+/*static*/ inline const AAT::Lookup<OT::Offset<OT::HBUINT16, false> >& Null<AAT::Lookup<OT::Offset<OT::HBUINT16, false> > > ()
+{ return *reinterpret_cast<const AAT::Lookup<OT::Offset<OT::HBUINT16, false> > *> (_hb_Null_AAT_Lookup); }
+namespace AAT {
+
+enum { DELETED_GLYPH = 0xFFFF };
+
+/*
+ * (Extended) State Table
+ */
+
+template <typename T>
+struct Entry
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    /* Note, we don't recurse-sanitize data because we don't access it.
+     * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
+     * which ensures that data has a simple sanitize(). To be determined
+     * if I need to remove that as well.
+     *
+     * HOWEVER! Because we are a template, our DEFINE_SIZE_STATIC
+     * assertion wouldn't be checked, hence the line below. */
+    static_assert (T::static_size, "");
+
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16      newState;       /* Byte offset from beginning of state table
+                                 * to the new state. Really?!?! Or just state
+                                 * number?  The latter in morx for sure. */
+  HBUINT16      flags;          /* Table specific. */
+  T             data;           /* Optional offsets to per-glyph tables. */
+  public:
+  DEFINE_SIZE_STATIC (4 + T::static_size);
+};
+
+template <>
+struct Entry<void>
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16      newState;       /* Byte offset from beginning of state table to the new state. */
+  HBUINT16      flags;          /* Table specific. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+template <typename Types, typename Extra>
+struct StateTable
+{
+  typedef typename Types::HBUINT HBUINT;
+  typedef typename Types::HBUSHORT HBUSHORT;
+  typedef typename Types::ClassTypeNarrow ClassType;
+
+  enum State
+  {
+    STATE_START_OF_TEXT = 0,
+    STATE_START_OF_LINE = 1,
+  };
+  enum Class
+  {
+    CLASS_END_OF_TEXT = 0,
+    CLASS_OUT_OF_BOUNDS = 1,
+    CLASS_DELETED_GLYPH = 2,
+    CLASS_END_OF_LINE = 3,
+  };
+
+  int new_state (unsigned int newState) const
+  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
+
+  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+  {
+    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
+    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
+  }
+
+  const Entry<Extra> *get_entries () const
+  { return (this+entryTable).arrayZ; }
+
+  const Entry<Extra> &get_entry (int state, unsigned int klass) const
+  {
+    if (unlikely (klass >= nClasses))
+      klass = StateTable<Types, Entry<Extra> >::CLASS_OUT_OF_BOUNDS;
+
+    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
+    const Entry<Extra> *entries = (this+entryTable).arrayZ;
+
+    unsigned int entry = states[state * nClasses + klass];
+    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
+
+    return entries[entry];
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 unsigned int *num_entries_out = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this) &&
+                    nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
+                    classTable.sanitize (c, this)))) return_trace (false);
+
+    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
+    const Entry<Extra> *entries = (this+entryTable).arrayZ;
+
+    unsigned int num_classes = nClasses;
+    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
+      return_trace (false);
+    unsigned int row_stride = num_classes * states[0].static_size;
+
+    /* Apple 'kern' table has this peculiarity:
+     *
+     * "Because the stateTableOffset in the state table header is (strictly
+     * speaking) redundant, some 'kern' tables use it to record an initial
+     * state where that should not be StartOfText. To determine if this is
+     * done, calculate what the stateTableOffset should be. If it's different
+     * from the actual stateTableOffset, use it as the initial state."
+     *
+     * We implement this by calling the initial state zero, but allow *negative*
+     * states if the start state indeed was not the first state.  Since the code
+     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
+     * tables are not affected since those address states by index, not offset.
+     */
+
+    int min_state = 0;
+    int max_state = 0;
+    unsigned int num_entries = 0;
+
+    int state_pos = 0;
+    int state_neg = 0;
+    unsigned int entry = 0;
+    while (min_state < state_neg || state_pos <= max_state)
+    {
+      if (min_state < state_neg)
+      {
+        /* Negative states. */
+        if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
+          return_trace (false);
+        if (unlikely (!c->check_range (&states[min_state * num_classes],
+                                       -min_state,
+                                       row_stride)))
+          return_trace (false);
+        if ((c->max_ops -= state_neg - min_state) <= 0)
+          return_trace (false);
+        { /* Sweep new states. */
+          const HBUSHORT *stop = &states[min_state * num_classes];
+          if (unlikely (stop > states))
+            return_trace (false);
+          for (const HBUSHORT *p = states; stop < p; p--)
+            num_entries = MAX<unsigned int> (num_entries, *(p - 1) + 1);
+          state_neg = min_state;
+        }
+      }
+
+      if (state_pos <= max_state)
+      {
+        /* Positive states. */
+        if (unlikely (!c->check_range (states,
+                                       max_state + 1,
+                                       row_stride)))
+          return_trace (false);
+        if ((c->max_ops -= max_state - state_pos + 1) <= 0)
+          return_trace (false);
+        { /* Sweep new states. */
+          if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
+            return_trace (false);
+          const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
+          if (unlikely (stop < states))
+            return_trace (false);
+          for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
+            num_entries = MAX<unsigned int> (num_entries, *p + 1);
+          state_pos = max_state + 1;
+        }
+      }
+
+      if (unlikely (!c->check_array (entries, num_entries)))
+        return_trace (false);
+      if ((c->max_ops -= num_entries - entry) <= 0)
+        return_trace (false);
+      { /* Sweep new entries. */
+        const Entry<Extra> *stop = &entries[num_entries];
+        for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
+        {
+          int newState = new_state (p->newState);
+          min_state = MIN (min_state, newState);
+          max_state = MAX (max_state, newState);
+        }
+        entry = num_entries;
+      }
+    }
+
+    if (num_entries_out)
+      *num_entries_out = num_entries;
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT        nClasses;       /* Number of classes, which is the number of indices
+                                 * in a single line in the state array. */
+  NNOffsetTo<ClassType, HBUINT>
+                classTable;     /* Offset to the class table. */
+  NNOffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
+                stateArrayTable;/* Offset to the state array. */
+  NNOffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT>
+                entryTable;     /* Offset to the entry array. */
+
+  public:
+  DEFINE_SIZE_STATIC (4 * sizeof (HBUINT));
+};
+
+template <typename HBUCHAR>
+struct ClassTable
+{
+  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int outOfRange) const
+  {
+    unsigned int i = glyph_id - firstGlyph;
+    return i >= classArray.len ? outOfRange : classArray.arrayZ[i];
+  }
+  unsigned int get_class (hb_codepoint_t glyph_id,
+                          unsigned int num_glyphs HB_UNUSED,
+                          unsigned int outOfRange) const
+  {
+    return get_class (glyph_id, outOfRange);
+  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && classArray.sanitize (c));
+  }
+  protected:
+  GlyphID               firstGlyph;     /* First glyph index included in the trimmed array. */
+  ArrayOf<HBUCHAR>      classArray;     /* The class codes (indexed by glyph index minus
+                                         * firstGlyph). */
+  public:
+  DEFINE_SIZE_ARRAY (4, classArray);
+};
+
+struct ObsoleteTypes
+{
+  static constexpr bool extended = false;
+  typedef HBUINT16 HBUINT;
+  typedef HBUINT8 HBUSHORT;
+  typedef ClassTable<HBUINT8> ClassTypeNarrow;
+  typedef ClassTable<HBUINT16> ClassTypeWide;
+
+  template <typename T>
+  static unsigned int offsetToIndex (unsigned int offset,
+                                     const void *base,
+                                     const T *array)
+  {
+    return (offset - ((const char *) array - (const char *) base)) / sizeof (T);
+  }
+  template <typename T>
+  static unsigned int byteOffsetToIndex (unsigned int offset,
+                                         const void *base,
+                                         const T *array)
+  {
+    return offsetToIndex (offset, base, array);
+  }
+  template <typename T>
+  static unsigned int wordOffsetToIndex (unsigned int offset,
+                                         const void *base,
+                                         const T *array)
+  {
+    return offsetToIndex (2 * offset, base, array);
+  }
+};
+struct ExtendedTypes
+{
+  static constexpr bool extended = true;
+  typedef HBUINT32 HBUINT;
+  typedef HBUINT16 HBUSHORT;
+  typedef Lookup<HBUINT16> ClassTypeNarrow;
+  typedef Lookup<HBUINT16> ClassTypeWide;
+
+  template <typename T>
+  static unsigned int offsetToIndex (unsigned int offset,
+                                     const void *base HB_UNUSED,
+                                     const T *array HB_UNUSED)
+  {
+    return offset;
+  }
+  template <typename T>
+  static unsigned int byteOffsetToIndex (unsigned int offset,
+                                         const void *base HB_UNUSED,
+                                         const T *array HB_UNUSED)
+  {
+    return offset / 2;
+  }
+  template <typename T>
+  static unsigned int wordOffsetToIndex (unsigned int offset,
+                                         const void *base HB_UNUSED,
+                                         const T *array HB_UNUSED)
+  {
+    return offset;
+  }
+};
+
+template <typename Types, typename EntryData>
+struct StateTableDriver
+{
+  StateTableDriver (const StateTable<Types, EntryData> &machine_,
+                    hb_buffer_t *buffer_,
+                    hb_face_t *face_) :
+              machine (machine_),
+              buffer (buffer_),
+              num_glyphs (face_->get_num_glyphs ()) {}
+
+  template <typename context_t>
+  void drive (context_t *c)
+  {
+    if (!c->in_place)
+      buffer->clear_output ();
+
+    int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT;
+    for (buffer->idx = 0; buffer->successful;)
+    {
+      unsigned int klass = buffer->idx < buffer->len ?
+                           machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
+                           (unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT;
+      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
+      const Entry<EntryData> &entry = machine.get_entry (state, klass);
+
+      /* Unsafe-to-break before this if not in state 0, as things might
+       * go differently if we start from state 0 here.
+       *
+       * Ugh.  The indexing here is ugly... */
+      if (state && buffer->backtrack_len () && buffer->idx < buffer->len)
+      {
+        /* If there's no action and we're just epsilon-transitioning to state 0,
+         * safe to break. */
+        if (c->is_actionable (this, entry) ||
+            !(entry.newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
+              entry.flags == context_t::DontAdvance))
+          buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
+      }
+
+      /* Unsafe-to-break if end-of-text would kick in here. */
+      if (buffer->idx + 2 <= buffer->len)
+      {
+        const Entry<EntryData> &end_entry = machine.get_entry (state, StateTable<Types, EntryData>::CLASS_END_OF_TEXT);
+        if (c->is_actionable (this, end_entry))
+          buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
+      }
+
+      c->transition (this, entry);
+
+      state = machine.new_state (entry.newState);
+      DEBUG_MSG (APPLY, nullptr, "s%d", state);
+
+      if (buffer->idx == buffer->len)
+        break;
+
+      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
+        buffer->next_glyph ();
+    }
+
+    if (!c->in_place)
+    {
+      for (; buffer->successful && buffer->idx < buffer->len;)
+        buffer->next_glyph ();
+      buffer->swap_buffers ();
+    }
+  }
+
+  public:
+  const StateTable<Types, EntryData> &machine;
+  hb_buffer_t *buffer;
+  unsigned int num_glyphs;
+};
+
+
+struct ankr;
+
+struct hb_aat_apply_context_t :
+       hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
+{
+  const char *get_name () { return "APPLY"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.apply (this); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  const hb_ot_shape_plan_t *plan;
+  hb_font_t *font;
+  hb_face_t *face;
+  hb_buffer_t *buffer;
+  hb_sanitize_context_t sanitizer;
+  const ankr *ankr_table;
+
+  /* Unused. For debug tracing only. */
+  unsigned int lookup_index;
+  unsigned int debug_depth;
+
+  HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
+                                      hb_font_t *font_,
+                                      hb_buffer_t *buffer_,
+                                      hb_blob_t *blob = const_cast<hb_blob_t *> (&Null(hb_blob_t)));
+
+  HB_INTERNAL ~hb_aat_apply_context_t ();
+
+  HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
+
+  void set_lookup_index (unsigned int i) { lookup_index = i; }
+};
+
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-feat-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,217 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_LAYOUT_FEAT_TABLE_HH
+#define HB_AAT_LAYOUT_FEAT_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+
+/*
+ * feat -- Feature Name
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6feat.html
+ */
+#define HB_AAT_TAG_feat HB_TAG('f','e','a','t')
+
+
+namespace AAT {
+
+
+struct SettingName
+{
+  friend struct FeatureName;
+
+  int cmp (hb_aat_layout_feature_selector_t key) const
+  { return (int) key - (int) setting; }
+
+  hb_aat_layout_feature_selector_t get_selector () const
+  { return (hb_aat_layout_feature_selector_t) (unsigned) setting; }
+
+  void get_info (hb_aat_layout_feature_selector_info_t *s,
+                        hb_aat_layout_feature_selector_t default_selector) const
+  {
+    s->name_id = nameIndex;
+
+    s->enable = (hb_aat_layout_feature_selector_t) (unsigned int) setting;
+    s->disable = default_selector == HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID ?
+                 (hb_aat_layout_feature_selector_t) (s->enable + 1) :
+                 default_selector;
+
+    s->reserved = 0;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      setting;        /* The setting. */
+  NameID        nameIndex;      /* The name table index for the setting's name. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+DECLARE_NULL_NAMESPACE_BYTES (AAT, SettingName);
+
+struct feat;
+
+struct FeatureName
+{
+  int cmp (hb_aat_layout_feature_type_t key) const
+  { return (int) key - (int) feature; }
+
+  enum {
+    Exclusive   = 0x8000,       /* If set, the feature settings are mutually exclusive. */
+    NotDefault  = 0x4000,       /* If clear, then the setting with an index of 0 in
+                                 * the setting name array for this feature should
+                                 * be taken as the default for the feature
+                                 * (if one is required). If set, then bits 0-15 of this
+                                 * featureFlags field contain the index of the setting
+                                 * which is to be taken as the default. */
+    IndexMask   = 0x00FF        /* If bits 30 and 31 are set, then these sixteen bits
+                                 * indicate the index of the setting in the setting name
+                                 * array for this feature which should be taken
+                                 * as the default. */
+  };
+
+  unsigned int get_selector_infos (unsigned int                           start_offset,
+                                   unsigned int                          *selectors_count, /* IN/OUT.  May be NULL. */
+                                   hb_aat_layout_feature_selector_info_t *selectors,       /* OUT.     May be NULL. */
+                                   unsigned int                          *pdefault_index,  /* OUT.     May be NULL. */
+                                   const void *base) const
+  {
+    hb_array_t< const SettingName> settings_table = (base+settingTableZ).as_array (nSettings);
+
+    static_assert (Index::NOT_FOUND_INDEX == HB_AAT_LAYOUT_NO_SELECTOR_INDEX, "");
+
+    hb_aat_layout_feature_selector_t default_selector = HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID;
+    unsigned int default_index = Index::NOT_FOUND_INDEX;
+    if (featureFlags & Exclusive)
+    {
+      default_index = (featureFlags & NotDefault) ? featureFlags & IndexMask : 0;
+      default_selector = settings_table[default_index].get_selector ();
+    }
+    if (pdefault_index)
+      *pdefault_index = default_index;
+
+    if (selectors_count)
+    {
+      hb_array_t<const SettingName> arr = settings_table.sub_array (start_offset, selectors_count);
+      for (unsigned int i = 0; i < arr.length; i++)
+        settings_table[start_offset + i].get_info (&selectors[i], default_selector);
+    }
+    return settings_table.length;
+  }
+
+  hb_aat_layout_feature_type_t get_feature_type () const
+  { return (hb_aat_layout_feature_type_t) (unsigned int) feature; }
+
+  hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (base+settingTableZ).sanitize (c, nSettings)));
+  }
+
+  protected:
+  HBUINT16      feature;        /* Feature type. */
+  HBUINT16      nSettings;      /* The number of records in the setting name array. */
+  LOffsetTo<UnsizedArrayOf<SettingName>, false>
+                settingTableZ;  /* Offset in bytes from the beginning of this table to
+                                 * this feature's setting name array. The actual type of
+                                 * record this offset refers to will depend on the
+                                 * exclusivity value, as described below. */
+  HBUINT16      featureFlags;   /* Single-bit flags associated with the feature type. */
+  HBINT16       nameIndex;      /* The name table index for the feature's name.
+                                 * This index has values greater than 255 and
+                                 * less than 32768. */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct feat
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_feat;
+
+  bool has_data () const { return version.to_int (); }
+
+  unsigned int get_feature_types (unsigned int                  start_offset,
+                                  unsigned int                 *count,
+                                  hb_aat_layout_feature_type_t *features) const
+  {
+    unsigned int feature_count = featureNameCount;
+    if (count && *count)
+    {
+      unsigned int len = MIN (feature_count - start_offset, *count);
+      for (unsigned int i = 0; i < len; i++)
+        features[i] = namesZ[i + start_offset].get_feature_type ();
+      *count = len;
+    }
+    return featureNameCount;
+  }
+
+  const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
+  {
+    return namesZ.bsearch (featureNameCount, feature_type);
+  }
+
+  hb_ot_name_id_t get_feature_name_id (hb_aat_layout_feature_type_t feature) const
+  { return get_feature (feature).get_feature_name_id (); }
+
+  unsigned int get_selector_infos (hb_aat_layout_feature_type_t           feature_type,
+                                   unsigned int                           start_offset,
+                                   unsigned int                          *selectors_count, /* IN/OUT.  May be NULL. */
+                                   hb_aat_layout_feature_selector_info_t *selectors,       /* OUT.     May be NULL. */
+                                   unsigned int                          *default_index    /* OUT.     May be NULL. */) const
+  {
+    return get_feature (feature_type).get_selector_infos (start_offset, selectors_count, selectors,
+                                                          default_index, this);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version.major == 1 &&
+                          namesZ.sanitize (c, featureNameCount, this)));
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version number of the feature name table
+                                 * (0x00010000 for the current version). */
+  HBUINT16      featureNameCount;
+                                /* The number of entries in the feature name array. */
+  HBUINT16      reserved1;      /* Reserved (set to zero). */
+  HBUINT32      reserved2;      /* Reserved (set to zero). */
+  SortedUnsizedArrayOf<FeatureName>
+                namesZ;         /* The feature name array. */
+  public:
+  DEFINE_SIZE_STATIC (24);
+};
+
+} /* namespace AAT */
+
+#endif /* HB_AAT_LAYOUT_FEAT_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-just-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,417 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_LAYOUT_JUST_TABLE_HH
+#define HB_AAT_LAYOUT_JUST_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
+
+#include "hb-aat-layout-morx-table.hh"
+
+/*
+ * just -- Justification
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6just.html
+ */
+#define HB_AAT_TAG_just HB_TAG('j','u','s','t')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+struct ActionSubrecordHeader
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  HBUINT16      actionClass;    /* The JustClass value associated with this
+                                 * ActionSubrecord. */
+  HBUINT16      actionType;     /* The type of postcompensation action. */
+  HBUINT16      actionLength;   /* Length of this ActionSubrecord record, which
+                                 * must be a multiple of 4. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct DecompositionAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  ActionSubrecordHeader
+                header;
+  Fixed         lowerLimit;     /* If the distance factor is less than this value,
+                                 * then the ligature is decomposed. */
+  Fixed         upperLimit;     /* If the distance factor is greater than this value,
+                                 * then the ligature is decomposed. */
+  HBUINT16      order;          /* Numerical order in which this ligature will
+                                 * be decomposed; you may want infrequent ligatures
+                                 * to decompose before more frequent ones. The ligatures
+                                 * on the line of text will decompose in increasing
+                                 * value of this field. */
+  ArrayOf<HBUINT16>
+                decomposedglyphs;
+                                /* Number of 16-bit glyph indexes that follow;
+                                 * the ligature will be decomposed into these glyphs.
+                                 *
+                                 * Array of decomposed glyphs. */
+  public:
+  DEFINE_SIZE_ARRAY (18, decomposedglyphs);
+};
+
+struct UnconditionalAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  ActionSubrecordHeader
+                header;
+  GlyphID       addGlyph;       /* Glyph that should be added if the distance factor
+                                 * is growing. */
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct ConditionalAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+                header;
+  Fixed         substThreshold; /* Distance growth factor (in ems) at which
+                                 * this glyph is replaced and the growth factor
+                                 * recalculated. */
+  GlyphID       addGlyph;       /* Glyph to be added as kashida. If this value is
+                                 * 0xFFFF, no extra glyph will be added. Note that
+                                 * generally when a glyph is added, justification
+                                 * will need to be redone. */
+  GlyphID       substGlyph;     /* Glyph to be substituted for this glyph if the
+                                 * growth factor equals or exceeds the value of
+                                 * substThreshold. */
+  public:
+  DEFINE_SIZE_STATIC (14);
+};
+
+struct DuctileGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+                header;
+  HBUINT32      variationAxis;  /* The 4-byte tag identifying the ductile axis.
+                                 * This would normally be 0x64756374 ('duct'),
+                                 * but you may use any axis the font contains. */
+  Fixed         minimumLimit;   /* The lowest value for the ductility axis tha
+                                 * still yields an acceptable appearance. Normally
+                                 * this will be 1.0. */
+  Fixed         noStretchValue; /* This is the default value that corresponds to
+                                 * no change in appearance. Normally, this will
+                                 * be 1.0. */
+  Fixed         maximumLimit;   /* The highest value for the ductility axis that
+                                 * still yields an acceptable appearance. */
+  public:
+  DEFINE_SIZE_STATIC (22);
+};
+
+struct RepeatedAddGlyphAction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  ActionSubrecordHeader
+                header;
+  HBUINT16      flags;          /* Currently unused; set to 0. */
+  GlyphID       glyph;          /* Glyph that should be added if the distance factor
+                                 * is growing. */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct ActionSubrecord
+{
+  unsigned int get_length () const { return u.header.actionLength; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    switch (u.header.actionType)
+    {
+    case 0:  return_trace (u.decompositionAction.sanitize (c));
+    case 1:  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
+    case 2:  return_trace (u.conditionalAddGlyphAction.sanitize (c));
+    // case 3: return_trace (u.stretchGlyphAction.sanitize (c));
+    case 4:  return_trace (u.decompositionAction.sanitize (c));
+    case 5:  return_trace (u.decompositionAction.sanitize (c));
+    default: return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  ActionSubrecordHeader         header;
+  DecompositionAction           decompositionAction;
+  UnconditionalAddGlyphAction   unconditionalAddGlyphAction;
+  ConditionalAddGlyphAction     conditionalAddGlyphAction;
+  /* StretchGlyphAction stretchGlyphAction; -- Not supported by CoreText */
+  DuctileGlyphAction            ductileGlyphAction;
+  RepeatedAddGlyphAction        repeatedAddGlyphAction;
+  } u;                          /* Data. The format of this data depends on
+                                 * the value of the actionType field. */
+  public:
+  DEFINE_SIZE_UNION (6, header);
+};
+
+struct PostcompensationActionChain
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+
+    unsigned int offset = min_size;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ActionSubrecord& subrecord = StructAtOffset<ActionSubrecord> (this, offset);
+      if (unlikely (!subrecord.sanitize (c))) return_trace (false);
+      offset += subrecord.get_length ();
+    }
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT32      count;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct JustWidthDeltaEntry
+{
+  enum Flags
+  {
+    Reserved1           =0xE000,/* Reserved. You should set these bits to zero. */
+    UnlimiteGap         =0x1000,/* The glyph can take unlimited gap. When this
+                                 * glyph participates in the justification process,
+                                 * it and any other glyphs on the line having this
+                                 * bit set absorb all the remaining gap. */
+    Reserved2           =0x0FF0,/* Reserved. You should set these bits to zero. */
+    Priority            =0x000F /* The justification priority of the glyph. */
+  };
+
+  enum Priority
+  {
+    Kashida             = 0,    /* Kashida priority. This is the highest priority
+                                 * during justification. */
+    Whitespace          = 1,    /* Whitespace priority. Any whitespace glyphs (as
+                                 * identified in the glyph properties table) will
+                                 * get this priority. */
+    InterCharacter      = 2,    /* Inter-character priority. Give this to any
+                                 * remaining glyphs. */
+    NullPriority        = 3     /* Null priority. You should set this priority for
+                                 * glyphs that only participate in justification
+                                 * after the above priorities. Normally all glyphs
+                                 * have one of the previous three values. If you
+                                 * don't want a glyph to participate in justification,
+                                 * and you don't want to set its factors to zero,
+                                 * you may instead assign it to the null priority. */
+  };
+
+  protected:
+  Fixed         beforeGrowLimit;/* The ratio by which the advance width of the
+                                 * glyph is permitted to grow on the left or top side. */
+  Fixed         beforeShrinkLimit;
+                                /* The ratio by which the advance width of the
+                                 * glyph is permitted to shrink on the left or top side. */
+  Fixed         afterGrowLimit; /* The ratio by which the advance width of the glyph
+                                 * is permitted to shrink on the left or top side. */
+  Fixed         afterShrinkLimit;
+                                /* The ratio by which the advance width of the glyph
+                                 * is at most permitted to shrink on the right or
+                                 * bottom side. */
+  HBUINT16      growFlags;      /* Flags controlling the grow case. */
+  HBUINT16      shrinkFlags;    /* Flags controlling the shrink case. */
+
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+struct WidthDeltaPair
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT32      justClass;      /* The justification category associated
+                                 * with the wdRecord field. Only 7 bits of
+                                 * this field are used. (The other bits are
+                                 * used as padding to guarantee longword
+                                 * alignment of the following record). */
+  JustWidthDeltaEntry
+                wdRecord;       /* The actual width delta record. */
+
+  public:
+  DEFINE_SIZE_STATIC (24);
+};
+
+typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
+
+struct JustificationCategory
+{
+  typedef void EntryData;
+
+  enum Flags
+  {
+    SetMark             =0x8000,/* If set, make the current glyph the marked
+                                 * glyph. */
+    DontAdvance         =0x4000,/* If set, don't advance to the next glyph before
+                                 * going to the new state. */
+    MarkCategory        =0x3F80,/* The justification category for the marked
+                                 * glyph if nonzero. */
+    CurrentCategory     =0x007F /* The justification category for the current
+                                 * glyph if nonzero. */
+  };
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          morphHeader.sanitize (c) &&
+                          stHeader.sanitize (c)));
+  }
+
+  protected:
+  ChainSubtable<ObsoleteTypes>
+                morphHeader;    /* Metamorphosis-style subtable header. */
+  StateTable<ObsoleteTypes, EntryData>
+                stHeader;       /* The justification insertion state table header */
+  public:
+  DEFINE_SIZE_STATIC (30);
+};
+
+struct JustificationHeader
+{
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          justClassTable.sanitize (c, base, base) &&
+                          wdcTable.sanitize (c, base) &&
+                          pcTable.sanitize (c, base) &&
+                          lookupTable.sanitize (c, base)));
+  }
+
+  protected:
+  OffsetTo<JustificationCategory>
+                justClassTable; /* Offset to the justification category state table. */
+  OffsetTo<WidthDeltaCluster>
+                wdcTable;       /* Offset from start of justification table to start
+                                 * of the subtable containing the width delta factors
+                                 * for the glyphs in your font.
+                                 *
+                                 * The width delta clusters table. */
+  OffsetTo<PostcompensationActionChain>
+                pcTable;        /* Offset from start of justification table to start
+                                 * of postcompensation subtable (set to zero if none).
+                                 *
+                                 * The postcompensation subtable, if present in the font. */
+  Lookup<OffsetTo<WidthDeltaCluster> >
+                lookupTable;    /* Lookup table associating glyphs with width delta
+                                 * clusters. See the description of Width Delta Clusters
+                                 * table for details on how to interpret the lookup values. */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct just
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_just;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) &&
+                          version.major == 1 &&
+                          horizData.sanitize (c, this, this) &&
+                          vertData.sanitize (c, this, this)));
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version of the justification table
+                                 * (0x00010000u for version 1.0). */
+  HBUINT16      format;         /* Format of the justification table (set to 0). */
+  OffsetTo<JustificationHeader>
+                horizData;      /* Byte offset from the start of the justification table
+                                 * to the header for tables that contain justification
+                                 * information for horizontal text.
+                                 * If you are not including this information,
+                                 * store 0. */
+  OffsetTo<JustificationHeader>
+                vertData;       /* ditto, vertical */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_JUST_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-kerx-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,1001 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_KERX_TABLE_HH
+#define HB_AAT_LAYOUT_KERX_TABLE_HH
+
+#include "hb-kern.hh"
+#include "hb-aat-layout-ankr-table.hh"
+
+/*
+ * kerx -- Extended Kerning
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kerx.html
+ */
+#define HB_AAT_TAG_kerx HB_TAG('k','e','r','x')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+static inline int
+kerxTupleKern (int value,
+               unsigned int tupleCount,
+               const void *base,
+               hb_aat_apply_context_t *c)
+{
+  if (likely (!tupleCount || !c)) return value;
+
+  unsigned int offset = value;
+  const FWORD *pv = &StructAtOffset<FWORD> (base, offset);
+  if (unlikely (!c->sanitizer.check_array (pv, tupleCount))) return 0;
+  return *pv;
+}
+
+
+struct hb_glyph_pair_t
+{
+  hb_codepoint_t left;
+  hb_codepoint_t right;
+};
+
+struct KernPair
+{
+  int get_kerning () const { return value; }
+
+  int cmp (const hb_glyph_pair_t &o) const
+  {
+    int ret = left.cmp (o.left);
+    if (ret) return ret;
+    return right.cmp (o.right);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  GlyphID       left;
+  GlyphID       right;
+  FWORD         value;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat0
+{
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                   hb_aat_apply_context_t *c = nullptr) const
+  {
+    hb_glyph_pair_t pair = {left, right};
+    int v = pairs.bsearch (pair).get_kerning ();
+    return kerxTupleKern (v, header.tuple_count (), this, c);
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  struct accelerator_t
+  {
+    const KerxSubTableFormat0 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat0 &table_,
+                   hb_aat_apply_context_t *c_) :
+                     table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (pairs.sanitize (c)));
+  }
+
+  protected:
+  KernSubTableHeader    header;
+  BinSearchArrayOf<KernPair, typename KernSubTableHeader::Types::HBUINT>
+                        pairs;  /* Sorted kern records. */
+  public:
+  DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 16, pairs);
+};
+
+
+template <bool extended>
+struct Format1Entry;
+
+template <>
+struct Format1Entry<true>
+{
+  enum Flags
+  {
+    Push                = 0x8000,       /* If set, push this glyph on the kerning stack. */
+    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph
+                                         * before going to the new state. */
+    Reset               = 0x2000,       /* If set, reset the kerning data (clear the stack) */
+    Reserved            = 0x1FFF,       /* Not used; set to 0. */
+  };
+
+  struct EntryData
+  {
+    HBUINT16    kernActionIndex;/* Index into the kerning value array. If
+                                 * this index is 0xFFFF, then no kerning
+                                 * is to be performed. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.data.kernActionIndex != 0xFFFF; }
+
+  static unsigned int kernActionIndex (const Entry<EntryData> &entry)
+  { return entry.data.kernActionIndex; }
+};
+template <>
+struct Format1Entry<false>
+{
+  enum Flags
+  {
+    Push                = 0x8000,       /* If set, push this glyph on the kerning stack. */
+    DontAdvance         = 0x4000,       /* If set, don't advance to the next glyph
+                                         * before going to the new state. */
+    Offset              = 0x3FFF,       /* Byte offset from beginning of subtable to the
+                                         * value table for the glyphs on the kerning stack. */
+
+    Reset               = 0x0000,       /* Not supported? */
+  };
+
+  typedef void EntryData;
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+
+  static unsigned int kernActionIndex (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat1
+{
+  typedef typename KernSubTableHeader::Types Types;
+  typedef typename Types::HBUINT HBUINT;
+
+  typedef Format1Entry<Types::extended> Format1EntryT;
+  typedef typename Format1EntryT::EntryData EntryData;
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum
+    {
+      DontAdvance       = Format1EntryT::DontAdvance,
+    };
+
+    driver_context_t (const KerxSubTableFormat1 *table_,
+                      hb_aat_apply_context_t *c_) :
+        c (c_),
+        table (table_),
+        /* Apparently the offset kernAction is from the beginning of the state-machine,
+         * similar to offsets in morx table, NOT from beginning of this table, like
+         * other subtables in kerx.  Discovered via testing. */
+        kernAction (&table->machine + table->kernAction),
+        depth (0),
+        crossStream (table->header.coverage & table->header.CrossStream) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return Format1EntryT::performAction (entry);
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry.flags;
+
+      if (flags & Format1EntryT::Reset)
+        depth = 0;
+
+      if (flags & Format1EntryT::Push)
+      {
+        if (likely (depth < ARRAY_LENGTH (stack)))
+          stack[depth++] = buffer->idx;
+        else
+          depth = 0; /* Probably not what CoreText does, but better? */
+      }
+
+      if (Format1EntryT::performAction (entry) && depth)
+      {
+        unsigned int tuple_count = MAX (1u, table->header.tuple_count ());
+
+        unsigned int kern_idx = Format1EntryT::kernActionIndex (entry);
+        kern_idx = Types::byteOffsetToIndex (kern_idx, &table->machine, kernAction.arrayZ);
+        const FWORD *actions = &kernAction[kern_idx];
+        if (!c->sanitizer.check_array (actions, depth, tuple_count))
+        {
+          depth = 0;
+          return;
+        }
+
+        hb_mask_t kern_mask = c->plan->kern_mask;
+
+        /* From Apple 'kern' spec:
+         * "Each pops one glyph from the kerning stack and applies the kerning value to it.
+         * The end of the list is marked by an odd value... */
+        bool last = false;
+        while (!last && depth)
+        {
+          unsigned int idx = stack[--depth];
+          int v = *actions;
+          actions += tuple_count;
+          if (idx >= buffer->len) continue;
+
+          /* "The end of the list is marked by an odd value..." */
+          last = v & 1;
+          v &= ~1;
+
+          hb_glyph_position_t &o = buffer->pos[idx];
+
+          /* Testing shows that CoreText only applies kern (cross-stream or not)
+           * if none has been applied by previous subtables.  That is, it does
+           * NOT seem to accumulate as otherwise implied by specs. */
+
+          /* The following flag is undocumented in the spec, but described
+           * in the 'kern' table example. */
+          if (v == -0x8000)
+          {
+            o.attach_type() = ATTACH_TYPE_NONE;
+            o.attach_chain() = 0;
+            o.x_offset = o.y_offset = 0;
+          }
+          else if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+          {
+            if (crossStream)
+            {
+              if (buffer->pos[idx].attach_type() && !buffer->pos[idx].y_offset)
+              {
+                o.y_offset = c->font->em_scale_y (v);
+                buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+              }
+            }
+            else if (buffer->info[idx].mask & kern_mask)
+            {
+              if (!buffer->pos[idx].x_offset)
+              {
+                buffer->pos[idx].x_advance += c->font->em_scale_x (v);
+                buffer->pos[idx].x_offset += c->font->em_scale_x (v);
+              }
+            }
+          }
+          else
+          {
+            if (crossStream)
+            {
+              /* CoreText doesn't do crossStream kerning in vertical.  We do. */
+              if (buffer->pos[idx].attach_type() && !buffer->pos[idx].x_offset)
+              {
+                o.x_offset = c->font->em_scale_x (v);
+                buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+              }
+            }
+            else if (buffer->info[idx].mask & kern_mask)
+            {
+              if (!buffer->pos[idx].y_offset)
+              {
+                buffer->pos[idx].y_advance += c->font->em_scale_y (v);
+                buffer->pos[idx].y_offset += c->font->em_scale_y (v);
+              }
+            }
+          }
+        }
+      }
+    }
+
+    private:
+    hb_aat_apply_context_t *c;
+    const KerxSubTableFormat1 *table;
+    const UnsizedArrayOf<FWORD> &kernAction;
+    unsigned int stack[8];
+    unsigned int depth;
+    bool crossStream;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning &&
+        !(header.coverage & header.CrossStream))
+      return false;
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+    driver.drive (&dc);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (likely (c->check_struct (this) &&
+                          machine.sanitize (c)));
+  }
+
+  protected:
+  KernSubTableHeader                            header;
+  StateTable<Types, EntryData>                  machine;
+  NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT>     kernAction;
+  public:
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 5 * sizeof (HBUINT));
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat2
+{
+  typedef typename KernSubTableHeader::Types Types;
+  typedef typename Types::HBUINT HBUINT;
+
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                   hb_aat_apply_context_t *c) const
+  {
+    unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
+    unsigned int l = (this+leftClassTable).get_class (left, num_glyphs, 0);
+    unsigned int r = (this+rightClassTable).get_class (right, num_glyphs, 0);
+
+    const UnsizedArrayOf<FWORD> &arrayZ = this+array;
+    unsigned int kern_idx = l + r;
+    kern_idx = Types::offsetToIndex (kern_idx, this, &arrayZ);
+    const FWORD *v = &arrayZ[kern_idx];
+    if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+
+    return kerxTupleKern (*v, header.tuple_count (), this, c);
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  struct accelerator_t
+  {
+    const KerxSubTableFormat2 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat2 &table_,
+                   hb_aat_apply_context_t *c_) :
+                     table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          leftClassTable.sanitize (c, this) &&
+                          rightClassTable.sanitize (c, this) &&
+                          c->check_range (this, array)));
+  }
+
+  protected:
+  KernSubTableHeader    header;
+  HBUINT                rowWidth;       /* The width, in bytes, of a row in the table. */
+  NNOffsetTo<typename Types::ClassTypeWide, HBUINT>
+                        leftClassTable; /* Offset from beginning of this subtable to
+                                         * left-hand class table. */
+  NNOffsetTo<typename Types::ClassTypeWide, HBUINT>
+                        rightClassTable;/* Offset from beginning of this subtable to
+                                         * right-hand class table. */
+  NNOffsetTo<UnsizedArrayOf<FWORD>, HBUINT>
+                         array;         /* Offset from beginning of this subtable to
+                                         * the start of the kerning array. */
+  public:
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 4 * sizeof (HBUINT));
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat4
+{
+  typedef ExtendedTypes Types;
+
+  struct EntryData
+  {
+    HBUINT16    ankrActionIndex;/* Either 0xFFFF (for no action) or the index of
+                                 * the action to perform. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
+      Mark              = 0x8000,       /* If set, remember this glyph as the marked glyph. */
+      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+                                         * going to the new state. */
+      Reserved          = 0x3FFF,       /* Not used; set to 0. */
+    };
+
+    enum SubTableFlags
+    {
+      ActionType        = 0xC0000000,   /* A two-bit field containing the action type. */
+      Unused            = 0x3F000000,   /* Unused - must be zero. */
+      Offset            = 0x00FFFFFF,   /* Masks the offset in bytes from the beginning
+                                         * of the subtable to the beginning of the control
+                                         * point table. */
+    };
+
+    driver_context_t (const KerxSubTableFormat4 *table,
+                             hb_aat_apply_context_t *c_) :
+        c (c_),
+        action_type ((table->flags & ActionType) >> 30),
+        ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))),
+        mark_set (false),
+        mark (0) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return entry.data.ankrActionIndex != 0xFFFF;
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len)
+      {
+        hb_glyph_position_t &o = buffer->cur_pos();
+        switch (action_type)
+        {
+          case 0: /* Control Point Actions.*/
+          {
+            /* indexed into glyph outline. */
+            const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
+            if (!c->sanitizer.check_array (data, 2)) return;
+            HB_UNUSED unsigned int markControlPoint = *data++;
+            HB_UNUSED unsigned int currControlPoint = *data++;
+            hb_position_t markX = 0;
+            hb_position_t markY = 0;
+            hb_position_t currX = 0;
+            hb_position_t currY = 0;
+            if (!c->font->get_glyph_contour_point_for_origin (c->buffer->info[mark].codepoint,
+                                                              markControlPoint,
+                                                              HB_DIRECTION_LTR /*XXX*/,
+                                                              &markX, &markY) ||
+                !c->font->get_glyph_contour_point_for_origin (c->buffer->cur ().codepoint,
+                                                              currControlPoint,
+                                                              HB_DIRECTION_LTR /*XXX*/,
+                                                              &currX, &currY))
+              return;
+
+            o.x_offset = markX - currX;
+            o.y_offset = markY - currY;
+          }
+          break;
+
+          case 1: /* Anchor Point Actions. */
+          {
+           /* Indexed into 'ankr' table. */
+            const HBUINT16 *data = &ankrData[entry.data.ankrActionIndex];
+            if (!c->sanitizer.check_array (data, 2)) return;
+            unsigned int markAnchorPoint = *data++;
+            unsigned int currAnchorPoint = *data++;
+            const Anchor &markAnchor = c->ankr_table->get_anchor (c->buffer->info[mark].codepoint,
+                                                                  markAnchorPoint,
+                                                                  c->sanitizer.get_num_glyphs ());
+            const Anchor &currAnchor = c->ankr_table->get_anchor (c->buffer->cur ().codepoint,
+                                                                  currAnchorPoint,
+                                                                  c->sanitizer.get_num_glyphs ());
+
+            o.x_offset = c->font->em_scale_x (markAnchor.xCoordinate) - c->font->em_scale_x (currAnchor.xCoordinate);
+            o.y_offset = c->font->em_scale_y (markAnchor.yCoordinate) - c->font->em_scale_y (currAnchor.yCoordinate);
+          }
+          break;
+
+          case 2: /* Control Point Coordinate Actions. */
+          {
+            const FWORD *data = (const FWORD *) &ankrData[entry.data.ankrActionIndex];
+            if (!c->sanitizer.check_array (data, 4)) return;
+            int markX = *data++;
+            int markY = *data++;
+            int currX = *data++;
+            int currY = *data++;
+
+            o.x_offset = c->font->em_scale_x (markX) - c->font->em_scale_x (currX);
+            o.y_offset = c->font->em_scale_y (markY) - c->font->em_scale_y (currY);
+          }
+          break;
+        }
+        o.attach_type() = ATTACH_TYPE_MARK;
+        o.attach_chain() = (int) mark - (int) buffer->idx;
+        buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+      }
+
+      if (entry.flags & Mark)
+      {
+        mark_set = true;
+        mark = buffer->idx;
+      }
+    }
+
+    private:
+    hb_aat_apply_context_t *c;
+    unsigned int action_type;
+    const HBUINT16 *ankrData;
+    bool mark_set;
+    unsigned int mark;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
+    driver.drive (&dc);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (likely (c->check_struct (this) &&
+                          machine.sanitize (c)));
+  }
+
+  protected:
+  KernSubTableHeader            header;
+  StateTable<Types, EntryData>  machine;
+  HBUINT32                      flags;
+  public:
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 20);
+};
+
+template <typename KernSubTableHeader>
+struct KerxSubTableFormat6
+{
+  enum Flags
+  {
+    ValuesAreLong       = 0x00000001,
+  };
+
+  bool is_long () const { return flags & ValuesAreLong; }
+
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
+                          hb_aat_apply_context_t *c) const
+  {
+    unsigned int num_glyphs = c->sanitizer.get_num_glyphs ();
+    if (is_long ())
+    {
+      const typename U::Long &t = u.l;
+      unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
+      unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
+      unsigned int offset = l + r;
+      if (unlikely (offset < l)) return 0; /* Addition overflow. */
+      if (unlikely (hb_unsigned_mul_overflows (offset, sizeof (FWORD32)))) return 0;
+      const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32));
+      if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+      return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
+    }
+    else
+    {
+      const typename U::Short &t = u.s;
+      unsigned int l = (this+t.rowIndexTable).get_value_or_null (left, num_glyphs);
+      unsigned int r = (this+t.columnIndexTable).get_value_or_null (right, num_glyphs);
+      unsigned int offset = l + r;
+      const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD));
+      if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
+      return kerxTupleKern (*v, header.tuple_count (), &(this+vector), c);
+    }
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    accelerator_t accel (*this, c);
+    hb_kern_machine_t<accelerator_t> machine (accel, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (is_long () ?
+                           (
+                             u.l.rowIndexTable.sanitize (c, this) &&
+                             u.l.columnIndexTable.sanitize (c, this) &&
+                             c->check_range (this, u.l.array)
+                           ) : (
+                             u.s.rowIndexTable.sanitize (c, this) &&
+                             u.s.columnIndexTable.sanitize (c, this) &&
+                             c->check_range (this, u.s.array)
+                           )) &&
+                          (header.tuple_count () == 0 ||
+                           c->check_range (this, vector))));
+  }
+
+  struct accelerator_t
+  {
+    const KerxSubTableFormat6 &table;
+    hb_aat_apply_context_t *c;
+
+    accelerator_t (const KerxSubTableFormat6 &table_,
+                   hb_aat_apply_context_t *c_) :
+                     table (table_), c (c_) {}
+
+    int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+    { return table.get_kerning (left, right, c); }
+  };
+
+  protected:
+  KernSubTableHeader            header;
+  HBUINT32                      flags;
+  HBUINT16                      rowCount;
+  HBUINT16                      columnCount;
+  union U
+  {
+    struct Long
+    {
+      LNNOffsetTo<Lookup<HBUINT32> >            rowIndexTable;
+      LNNOffsetTo<Lookup<HBUINT32> >            columnIndexTable;
+      LNNOffsetTo<UnsizedArrayOf<FWORD32> >     array;
+    } l;
+    struct Short
+    {
+      LNNOffsetTo<Lookup<HBUINT16> >            rowIndexTable;
+      LNNOffsetTo<Lookup<HBUINT16> >            columnIndexTable;
+      LNNOffsetTo<UnsizedArrayOf<FWORD> >       array;
+    } s;
+  } u;
+  LNNOffsetTo<UnsizedArrayOf<FWORD> >   vector;
+  public:
+  DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
+};
+
+
+struct KerxSubTableHeader
+{
+  typedef ExtendedTypes Types;
+
+  unsigned int tuple_count () const { return tupleCount; }
+  bool is_horizontal () const       { return !(coverage & Vertical); }
+
+  enum Coverage
+  {
+    Vertical    = 0x80000000u,  /* Set if table has vertical kerning values. */
+    CrossStream = 0x40000000u,  /* Set if table has cross-stream kerning values. */
+    Variation   = 0x20000000u,  /* Set if table has variation kerning values. */
+    Backwards   = 0x10000000u,  /* If clear, process the glyphs forwards, that
+                                 * is, from first to last in the glyph stream.
+                                 * If we, process them from last to first.
+                                 * This flag only applies to state-table based
+                                 * 'kerx' subtables (types 1 and 4). */
+    Reserved    = 0x0FFFFF00u,  /* Reserved, set to zero. */
+    SubtableType= 0x000000FFu,  /* Subtable type. */
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  public:
+  HBUINT32      length;
+  HBUINT32      coverage;
+  HBUINT32      tupleCount;
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct KerxSubTable
+{
+  friend struct kerx;
+
+  unsigned int get_size () const { return u.header.length; }
+  unsigned int get_type () const { return u.header.coverage & u.header.SubtableType; }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case 0:     return_trace (c->dispatch (u.format0));
+    case 1:     return_trace (c->dispatch (u.format1));
+    case 2:     return_trace (c->dispatch (u.format2));
+    case 4:     return_trace (c->dispatch (u.format4));
+    case 6:     return_trace (c->dispatch (u.format6));
+    default:    return_trace (c->default_return_value ());
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.header.sanitize (c) ||
+        u.header.length <= u.header.static_size ||
+        !c->check_range (this, u.header.length))
+      return_trace (false);
+
+    return_trace (dispatch (c));
+  }
+
+  public:
+  union {
+  KerxSubTableHeader                            header;
+  KerxSubTableFormat0<KerxSubTableHeader>       format0;
+  KerxSubTableFormat1<KerxSubTableHeader>       format1;
+  KerxSubTableFormat2<KerxSubTableHeader>       format2;
+  KerxSubTableFormat4<KerxSubTableHeader>       format4;
+  KerxSubTableFormat6<KerxSubTableHeader>       format6;
+  } u;
+  public:
+  DEFINE_SIZE_MIN (12);
+};
+
+
+/*
+ * The 'kerx' Table
+ */
+
+template <typename T>
+struct KerxTable
+{
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const T* thiz () const { return static_cast<const T *> (this); }
+
+  bool has_state_machine () const
+  {
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (st->get_type () == 1)
+        return true;
+      st = &StructAfter<SubTable> (*st);
+    }
+    return false;
+  }
+
+  bool has_cross_stream () const
+  {
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (st->u.header.coverage & st->u.header.CrossStream)
+        return true;
+      st = &StructAfter<SubTable> (*st);
+    }
+    return false;
+  }
+
+  int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+  {
+    typedef typename T::SubTable SubTable;
+
+    int v = 0;
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if ((st->u.header.coverage & (st->u.header.Variation | st->u.header.CrossStream)) ||
+          !st->u.header.is_horizontal ())
+        continue;
+      v += st->get_kerning (left, right);
+      st = &StructAfter<SubTable> (*st);
+    }
+    return v;
+  }
+
+  bool apply (AAT::hb_aat_apply_context_t *c) const
+  {
+    typedef typename T::SubTable SubTable;
+
+    bool ret = false;
+    bool seenCrossStream = false;
+    c->set_lookup_index (0);
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      bool reverse;
+
+      if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation))
+        goto skip;
+
+      if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ())
+        goto skip;
+
+      reverse = bool (st->u.header.coverage & st->u.header.Backwards) !=
+                HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
+
+      if (!c->buffer->message (c->font, "start %c%c%c%c subtable %d", HB_UNTAG (thiz()->tableTag), c->lookup_index))
+        goto skip;
+
+      if (!seenCrossStream &&
+          (st->u.header.coverage & st->u.header.CrossStream))
+      {
+        /* Attach all glyphs into a chain. */
+        seenCrossStream = true;
+        hb_glyph_position_t *pos = c->buffer->pos;
+        unsigned int count = c->buffer->len;
+        for (unsigned int i = 0; i < count; i++)
+        {
+          pos[i].attach_type() = ATTACH_TYPE_CURSIVE;
+          pos[i].attach_chain() = HB_DIRECTION_IS_FORWARD (c->buffer->props.direction) ? -1 : +1;
+          /* We intentionally don't set HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT,
+           * since there needs to be a non-zero attachment for post-positioning to
+           * be needed. */
+        }
+      }
+
+      if (reverse)
+        c->buffer->reverse ();
+
+      {
+        /* See comment in sanitize() for conditional here. */
+        hb_sanitize_with_object_t with (&c->sanitizer, i < count - 1 ? st : (const SubTable *) nullptr);
+        ret |= st->dispatch (c);
+      }
+
+      if (reverse)
+        c->buffer->reverse ();
+
+      (void) c->buffer->message (c->font, "end %c%c%c%c subtable %d", HB_UNTAG (thiz()->tableTag), c->lookup_index);
+
+    skip:
+      st = &StructAfter<SubTable> (*st);
+      c->set_lookup_index (c->lookup_index + 1);
+    }
+
+    return ret;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!thiz()->version.sanitize (c) ||
+                  (unsigned) thiz()->version < (unsigned) T::minVersion ||
+                  !thiz()->tableCount.sanitize (c)))
+      return_trace (false);
+
+    typedef typename T::SubTable SubTable;
+
+    const SubTable *st = &thiz()->firstSubTable;
+    unsigned int count = thiz()->tableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (unlikely (!st->u.header.sanitize (c)))
+        return_trace (false);
+      /* OpenType kern table has 2-byte subtable lengths.  That's limiting.
+       * MS implementation also only supports one subtable, of format 0,
+       * anyway.  Certain versions of some fonts, like Calibry, contain
+       * kern subtable that exceeds 64kb.  Looks like, the subtable length
+       * is simply ignored.  Which makes sense.  It's only needed if you
+       * have multiple subtables.  To handle such fonts, we just ignore
+       * the length for the last subtable. */
+      hb_sanitize_with_object_t with (c, i < count - 1 ? st : (const SubTable *) nullptr);
+
+      if (unlikely (!st->sanitize (c)))
+        return_trace (false);
+
+      st = &StructAfter<SubTable> (*st);
+    }
+
+    return_trace (true);
+  }
+};
+
+struct kerx : KerxTable<kerx>
+{
+  friend struct KerxTable<kerx>;
+
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_kerx;
+  static constexpr unsigned minVersion = 2u;
+
+  typedef KerxSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KerxSubTable SubTable;
+
+  bool has_data () const { return version; }
+
+  protected:
+  HBUINT16      version;        /* The version number of the extended kerning table
+                                 * (currently 2, 3, or 4). */
+  HBUINT16      unused;         /* Set to 0. */
+  HBUINT32      tableCount;     /* The number of subtables included in the extended kerning
+                                 * table. */
+  SubTable      firstSubTable;  /* Subtables. */
+/*subtableGlyphCoverageArray*/  /* Only if version >= 3. We don't use. */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_KERX_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-lcar-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+#ifndef HB_AAT_LAYOUT_LCAR_TABLE_HH
+#define HB_AAT_LAYOUT_LCAR_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+
+/*
+ * lcar -- Ligature caret
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6lcar.html
+ */
+#define HB_AAT_TAG_lcar HB_TAG('l','c','a','r')
+
+
+namespace AAT {
+
+typedef ArrayOf<HBINT16> LigCaretClassEntry;
+
+struct lcar
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_lcar;
+
+  unsigned int get_lig_carets (hb_font_t      *font,
+                               hb_direction_t  direction,
+                               hb_codepoint_t  glyph,
+                               unsigned int    start_offset,
+                               unsigned int   *caret_count /* IN/OUT */,
+                               hb_position_t  *caret_array /* OUT */) const
+  {
+    const OffsetTo<LigCaretClassEntry>* entry_offset = lookup.get_value (glyph,
+                                                                         font->face->get_num_glyphs ());
+    const LigCaretClassEntry& array = entry_offset ? this+*entry_offset : Null (LigCaretClassEntry);
+    if (caret_count)
+    {
+      hb_array_t<const HBINT16> arr = array.sub_array (start_offset, caret_count);
+      unsigned int count = arr.length;
+      for (unsigned int i = 0; i < count; ++i)
+        switch (format)
+        {
+        case 0: caret_array[i] = font->em_scale_dir (arr[i], direction); break;
+        case 1:
+          hb_position_t x, y;
+          font->get_glyph_contour_point_for_origin (glyph, arr[i], direction, &x, &y);
+          caret_array[i] = HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
+          break;
+        }
+    }
+    return array.len;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version.major == 1 &&
+                          lookup.sanitize (c, this)));
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version number of the ligature caret table */
+  HBUINT16      format;         /* Format of the ligature caret table. */
+  Lookup<OffsetTo<LigCaretClassEntry> >
+                lookup;         /* data Lookup table associating glyphs */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace AAT */
+
+#endif /* HB_AAT_LAYOUT_LCAR_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-morx-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,1159 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_MORX_TABLE_HH
+#define HB_AAT_LAYOUT_MORX_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-aat-map.hh"
+
+/*
+ * morx -- Extended Glyph Metamorphosis
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
+ */
+#define HB_AAT_TAG_morx HB_TAG('m','o','r','x')
+#define HB_AAT_TAG_mort HB_TAG('m','o','r','t')
+
+
+namespace AAT {
+
+using namespace OT;
+
+template <typename Types>
+struct RearrangementSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  typedef void EntryData;
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
+      MarkFirst         = 0x8000,       /* If set, make the current glyph the first
+                                         * glyph to be rearranged. */
+      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph
+                                         * before going to the new state. This means
+                                         * that the glyph index doesn't change, even
+                                         * if the glyph at that index has changed. */
+      MarkLast          = 0x2000,       /* If set, make the current glyph the last
+                                         * glyph to be rearranged. */
+      Reserved          = 0x1FF0,       /* These bits are reserved and should be set to 0. */
+      Verb              = 0x000F,       /* The type of rearrangement specified. */
+    };
+
+    driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
+        ret (false),
+        start (0), end (0) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return (entry.flags & Verb) && start < end;
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry.flags;
+
+      if (flags & MarkFirst)
+        start = buffer->idx;
+
+      if (flags & MarkLast)
+        end = MIN (buffer->idx + 1, buffer->len);
+
+      if ((flags & Verb) && start < end)
+      {
+        /* The following map has two nibbles, for start-side
+         * and end-side. Values of 0,1,2 mean move that many
+         * to the other side. Value of 3 means move 2 and
+         * flip them. */
+        const unsigned char map[16] =
+        {
+          0x00, /* 0    no change */
+          0x10, /* 1    Ax => xA */
+          0x01, /* 2    xD => Dx */
+          0x11, /* 3    AxD => DxA */
+          0x20, /* 4    ABx => xAB */
+          0x30, /* 5    ABx => xBA */
+          0x02, /* 6    xCD => CDx */
+          0x03, /* 7    xCD => DCx */
+          0x12, /* 8    AxCD => CDxA */
+          0x13, /* 9    AxCD => DCxA */
+          0x21, /* 10   ABxD => DxAB */
+          0x31, /* 11   ABxD => DxBA */
+          0x22, /* 12   ABxCD => CDxAB */
+          0x32, /* 13   ABxCD => CDxBA */
+          0x23, /* 14   ABxCD => DCxAB */
+          0x33, /* 15   ABxCD => DCxBA */
+        };
+
+        unsigned int m = map[flags & Verb];
+        unsigned int l = MIN<unsigned int> (2, m >> 4);
+        unsigned int r = MIN<unsigned int> (2, m & 0x0F);
+        bool reverse_l = 3 == (m >> 4);
+        bool reverse_r = 3 == (m & 0x0F);
+
+        if (end - start >= l + r)
+        {
+          buffer->merge_clusters (start, MIN (buffer->idx + 1, buffer->len));
+          buffer->merge_clusters (start, end);
+
+          hb_glyph_info_t *info = buffer->info;
+          hb_glyph_info_t buf[4];
+
+          memcpy (buf, info + start, l * sizeof (buf[0]));
+          memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
+
+          if (l != r)
+            memmove (info + start + r, info + start + l, (end - start - l - r) * sizeof (buf[0]));
+
+          memcpy (info + start, buf + 2, r * sizeof (buf[0]));
+          memcpy (info + end - l, buf, l * sizeof (buf[0]));
+          if (reverse_l)
+          {
+            buf[0] = info[end - 1];
+            info[end - 1] = info[end - 2];
+            info[end - 2] = buf[0];
+          }
+          if (reverse_r)
+          {
+            buf[0] = info[start];
+            info[start] = info[start + 1];
+            info[start + 1] = buf[0];
+          }
+        }
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    unsigned int start;
+    unsigned int end;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (machine.sanitize (c));
+  }
+
+  protected:
+  StateTable<Types, EntryData>  machine;
+  public:
+  DEFINE_SIZE_STATIC (16);
+};
+
+template <typename Types>
+struct ContextualSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  struct EntryData
+  {
+    HBUINT16    markIndex;      /* Index of the substitution table for the
+                                 * marked glyph (use 0xFFFF for none). */
+    HBUINT16    currentIndex;   /* Index of the substitution table for the
+                                 * current glyph (use 0xFFFF for none). */
+    public:
+    DEFINE_SIZE_STATIC (4);
+  };
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = true;
+    enum Flags
+    {
+      SetMark           = 0x8000,       /* If set, make the current glyph the marked glyph. */
+      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+                                         * going to the new state. */
+      Reserved          = 0x3FFF,       /* These bits are reserved and should be set to 0. */
+    };
+
+    driver_context_t (const ContextualSubtable *table_,
+                             hb_aat_apply_context_t *c_) :
+        ret (false),
+        c (c_),
+        mark_set (false),
+        mark (0),
+        table (table_),
+        subs (table+table->substitutionTables) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver,
+                        const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      if (buffer->idx == buffer->len && !mark_set)
+        return false;
+
+      return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF;
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      /* Looks like CoreText applies neither mark nor current substitution for
+       * end-of-text if mark was not explicitly set. */
+      if (buffer->idx == buffer->len && !mark_set)
+        return;
+
+      const GlyphID *replacement;
+
+      replacement = nullptr;
+      if (Types::extended)
+      {
+        if (entry.data.markIndex != 0xFFFF)
+        {
+          const Lookup<GlyphID> &lookup = subs[entry.data.markIndex];
+          replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
+        }
+      }
+      else
+      {
+        unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
+        const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
+        replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+        if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+          replacement = nullptr;
+      }
+      if (replacement)
+      {
+        buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
+        buffer->info[mark].codepoint = *replacement;
+        ret = true;
+      }
+
+      replacement = nullptr;
+      unsigned int idx = MIN (buffer->idx, buffer->len - 1);
+      if (Types::extended)
+      {
+        if (entry.data.currentIndex != 0xFFFF)
+        {
+          const Lookup<GlyphID> &lookup = subs[entry.data.currentIndex];
+          replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
+        }
+      }
+      else
+      {
+        unsigned int offset = entry.data.currentIndex + buffer->info[idx].codepoint;
+        const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
+        replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+        if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+          replacement = nullptr;
+      }
+      if (replacement)
+      {
+        buffer->info[idx].codepoint = *replacement;
+        ret = true;
+      }
+
+      if (entry.flags & SetMark)
+      {
+        mark_set = true;
+        mark = buffer->idx;
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    hb_aat_apply_context_t *c;
+    bool mark_set;
+    unsigned int mark;
+    const ContextualSubtable *table;
+    const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false> &subs;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    unsigned int num_entries = 0;
+    if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
+
+    if (!Types::extended)
+      return_trace (substitutionTables.sanitize (c, this, 0));
+
+    unsigned int num_lookups = 0;
+
+    const Entry<EntryData> *entries = machine.get_entries ();
+    for (unsigned int i = 0; i < num_entries; i++)
+    {
+      const EntryData &data = entries[i].data;
+
+      if (data.markIndex != 0xFFFF)
+        num_lookups = MAX<unsigned int> (num_lookups, 1 + data.markIndex);
+      if (data.currentIndex != 0xFFFF)
+        num_lookups = MAX<unsigned int> (num_lookups, 1 + data.currentIndex);
+    }
+
+    return_trace (substitutionTables.sanitize (c, this, num_lookups));
+  }
+
+  protected:
+  StateTable<Types, EntryData>
+                machine;
+  NNOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false>, HBUINT>
+                substitutionTables;
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+
+template <bool extended>
+struct LigatureEntry;
+
+template <>
+struct LigatureEntry<true>
+{
+  enum Flags
+  {
+    SetComponent        = 0x8000,       /* Push this glyph onto the component stack for
+                                         * eventual processing. */
+    DontAdvance         = 0x4000,       /* Leave the glyph pointer at this glyph for the
+                                           next iteration. */
+    PerformAction       = 0x2000,       /* Use the ligActionIndex to process a ligature
+                                         * group. */
+    Reserved            = 0x1FFF,       /* These bits are reserved and should be set to 0. */
+  };
+
+  struct EntryData
+  {
+    HBUINT16    ligActionIndex; /* Index to the first ligActionTable entry
+                                 * for processing this group, if indicated
+                                 * by the flags. */
+    public:
+    DEFINE_SIZE_STATIC (2);
+  };
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & PerformAction; }
+
+  static unsigned int ligActionIndex (const Entry<EntryData> &entry)
+  { return entry.data.ligActionIndex; }
+};
+template <>
+struct LigatureEntry<false>
+{
+  enum Flags
+  {
+    SetComponent        = 0x8000,       /* Push this glyph onto the component stack for
+                                         * eventual processing. */
+    DontAdvance         = 0x4000,       /* Leave the glyph pointer at this glyph for the
+                                           next iteration. */
+    Offset              = 0x3FFF,       /* Byte offset from beginning of subtable to the
+                                         * ligature action list. This value must be a
+                                         * multiple of 4. */
+  };
+
+  typedef void EntryData;
+
+  static bool performAction (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+
+  static unsigned int ligActionIndex (const Entry<EntryData> &entry)
+  { return entry.flags & Offset; }
+};
+
+
+template <typename Types>
+struct LigatureSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  typedef LigatureEntry<Types::extended> LigatureEntryT;
+  typedef typename LigatureEntryT::EntryData EntryData;
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = false;
+    enum
+    {
+      DontAdvance       = LigatureEntryT::DontAdvance,
+    };
+    enum LigActionFlags
+    {
+      LigActionLast     = 0x80000000,   /* This is the last action in the list. This also
+                                         * implies storage. */
+      LigActionStore    = 0x40000000,   /* Store the ligature at the current cumulated index
+                                         * in the ligature table in place of the marked
+                                         * (i.e. currently-popped) glyph. */
+      LigActionOffset   = 0x3FFFFFFF,   /* A 30-bit value which is sign-extended to 32-bits
+                                         * and added to the glyph ID, resulting in an index
+                                         * into the component table. */
+    };
+
+    driver_context_t (const LigatureSubtable *table_,
+                      hb_aat_apply_context_t *c_) :
+        ret (false),
+        c (c_),
+        table (table_),
+        ligAction (table+table->ligAction),
+        component (table+table->component),
+        ligature (table+table->ligature),
+        match_length (0) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return LigatureEntryT::performAction (entry);
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+
+      DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx);
+      if (entry.flags & LigatureEntryT::SetComponent)
+      {
+        /* Never mark same index twice, in case DontAdvance was used... */
+        if (match_length && match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] == buffer->out_len)
+          match_length--;
+
+        match_positions[match_length++ % ARRAY_LENGTH (match_positions)] = buffer->out_len;
+        DEBUG_MSG (APPLY, nullptr, "Set component at %u", buffer->out_len);
+      }
+
+      if (LigatureEntryT::performAction (entry))
+      {
+        DEBUG_MSG (APPLY, nullptr, "Perform action with %u", match_length);
+        unsigned int end = buffer->out_len;
+
+        if (unlikely (!match_length))
+          return;
+
+        if (buffer->idx >= buffer->len)
+          return; /* TODO Work on previous instead? */
+
+        unsigned int cursor = match_length;
+
+        unsigned int action_idx = LigatureEntryT::ligActionIndex (entry);
+        action_idx = Types::offsetToIndex (action_idx, table, ligAction.arrayZ);
+        const HBUINT32 *actionData = &ligAction[action_idx];
+
+        unsigned int ligature_idx = 0;
+        unsigned int action;
+        do
+        {
+          if (unlikely (!cursor))
+          {
+            /* Stack underflow.  Clear the stack. */
+            DEBUG_MSG (APPLY, nullptr, "Stack underflow");
+            match_length = 0;
+            break;
+          }
+
+          DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1);
+          buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]);
+
+          if (unlikely (!actionData->sanitize (&c->sanitizer))) break;
+          action = *actionData;
+
+          uint32_t uoffset = action & LigActionOffset;
+          if (uoffset & 0x20000000)
+            uoffset |= 0xC0000000; /* Sign-extend. */
+          int32_t offset = (int32_t) uoffset;
+          unsigned int component_idx = buffer->cur().codepoint + offset;
+          component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
+          const HBUINT16 &componentData = component[component_idx];
+          if (unlikely (!componentData.sanitize (&c->sanitizer))) break;
+          ligature_idx += componentData;
+
+          DEBUG_MSG (APPLY, nullptr, "Action store %u last %u",
+                     bool (action & LigActionStore),
+                     bool (action & LigActionLast));
+          if (action & (LigActionStore | LigActionLast))
+          {
+            ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
+            const GlyphID &ligatureData = ligature[ligature_idx];
+            if (unlikely (!ligatureData.sanitize (&c->sanitizer))) break;
+            hb_codepoint_t lig = ligatureData;
+
+            DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig);
+            buffer->replace_glyph (lig);
+
+            unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u;
+            /* Now go and delete all subsequent components. */
+            while (match_length - 1u > cursor)
+            {
+              DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
+              buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]);
+              buffer->replace_glyph (DELETED_GLYPH);
+            }
+
+            buffer->move_to (lig_end);
+            buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len);
+          }
+
+          actionData++;
+        }
+        while (!(action & LigActionLast));
+        buffer->move_to (end);
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    hb_aat_apply_context_t *c;
+    const LigatureSubtable *table;
+    const UnsizedArrayOf<HBUINT32> &ligAction;
+    const UnsizedArrayOf<HBUINT16> &component;
+    const UnsizedArrayOf<GlyphID> &ligature;
+    unsigned int match_length;
+    unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (c->check_struct (this) && machine.sanitize (c) &&
+                  ligAction && component && ligature);
+  }
+
+  protected:
+  StateTable<Types, EntryData>
+                machine;
+  NNOffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT>
+                ligAction;      /* Offset to the ligature action table. */
+  NNOffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT>
+                component;      /* Offset to the component table. */
+  NNOffsetTo<UnsizedArrayOf<GlyphID>, HBUINT>
+                ligature;       /* Offset to the actual ligature lists. */
+  public:
+  DEFINE_SIZE_STATIC (28);
+};
+
+template <typename Types>
+struct NoncontextualSubtable
+{
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    bool ret = false;
+    unsigned int num_glyphs = c->face->get_num_glyphs ();
+
+    hb_glyph_info_t *info = c->buffer->info;
+    unsigned int count = c->buffer->len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const GlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
+      if (replacement)
+      {
+        info[i].codepoint = *replacement;
+        ret = true;
+      }
+    }
+
+    return_trace (ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (substitute.sanitize (c));
+  }
+
+  protected:
+  Lookup<GlyphID>       substitute;
+  public:
+  DEFINE_SIZE_MIN (2);
+};
+
+template <typename Types>
+struct InsertionSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  struct EntryData
+  {
+    HBUINT16    currentInsertIndex;     /* Zero-based index into the insertion glyph table.
+                                         * The number of glyphs to be inserted is contained
+                                         * in the currentInsertCount field in the flags.
+                                         * A value of 0xFFFF indicates no insertion is to
+                                         * be done. */
+    HBUINT16    markedInsertIndex;      /* Zero-based index into the insertion glyph table.
+                                         * The number of glyphs to be inserted is contained
+                                         * in the markedInsertCount field in the flags.
+                                         * A value of 0xFFFF indicates no insertion is to
+                                         * be done. */
+    public:
+    DEFINE_SIZE_STATIC (4);
+  };
+
+  struct driver_context_t
+  {
+    static constexpr bool in_place = false;
+    enum Flags
+    {
+      SetMark           = 0x8000,       /* If set, mark the current glyph. */
+      DontAdvance       = 0x4000,       /* If set, don't advance to the next glyph before
+                                         * going to the new state.  This does not mean
+                                         * that the glyph pointed to is the same one as
+                                         * before. If you've made insertions immediately
+                                         * downstream of the current glyph, the next glyph
+                                         * processed would in fact be the first one
+                                         * inserted. */
+      CurrentIsKashidaLike= 0x2000,     /* If set, and the currentInsertList is nonzero,
+                                         * then the specified glyph list will be inserted
+                                         * as a kashida-like insertion, either before or
+                                         * after the current glyph (depending on the state
+                                         * of the currentInsertBefore flag). If clear, and
+                                         * the currentInsertList is nonzero, then the
+                                         * specified glyph list will be inserted as a
+                                         * split-vowel-like insertion, either before or
+                                         * after the current glyph (depending on the state
+                                         * of the currentInsertBefore flag). */
+      MarkedIsKashidaLike= 0x1000,      /* If set, and the markedInsertList is nonzero,
+                                         * then the specified glyph list will be inserted
+                                         * as a kashida-like insertion, either before or
+                                         * after the marked glyph (depending on the state
+                                         * of the markedInsertBefore flag). If clear, and
+                                         * the markedInsertList is nonzero, then the
+                                         * specified glyph list will be inserted as a
+                                         * split-vowel-like insertion, either before or
+                                         * after the marked glyph (depending on the state
+                                         * of the markedInsertBefore flag). */
+      CurrentInsertBefore= 0x0800,      /* If set, specifies that insertions are to be made
+                                         * to the left of the current glyph. If clear,
+                                         * they're made to the right of the current glyph. */
+      MarkedInsertBefore= 0x0400,       /* If set, specifies that insertions are to be
+                                         * made to the left of the marked glyph. If clear,
+                                         * they're made to the right of the marked glyph. */
+      CurrentInsertCount= 0x3E0,        /* This 5-bit field is treated as a count of the
+                                         * number of glyphs to insert at the current
+                                         * position. Since zero means no insertions, the
+                                         * largest number of insertions at any given
+                                         * current location is 31 glyphs. */
+      MarkedInsertCount= 0x001F,        /* This 5-bit field is treated as a count of the
+                                         * number of glyphs to insert at the marked
+                                         * position. Since zero means no insertions, the
+                                         * largest number of insertions at any given
+                                         * marked location is 31 glyphs. */
+    };
+
+    driver_context_t (const InsertionSubtable *table,
+                      hb_aat_apply_context_t *c_) :
+        ret (false),
+        c (c_),
+        mark (0),
+        insertionAction (table+table->insertionAction) {}
+
+    bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED,
+                        const Entry<EntryData> &entry)
+    {
+      return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) &&
+             (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF);
+    }
+    void transition (StateTableDriver<Types, EntryData> *driver,
+                     const Entry<EntryData> &entry)
+    {
+      hb_buffer_t *buffer = driver->buffer;
+      unsigned int flags = entry.flags;
+
+      unsigned mark_loc = buffer->out_len;
+
+      if (entry.data.markedInsertIndex != 0xFFFF)
+      {
+        unsigned int count = (flags & MarkedInsertCount);
+        unsigned int start = entry.data.markedInsertIndex;
+        const GlyphID *glyphs = &insertionAction[start];
+        if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+
+        bool before = flags & MarkedInsertBefore;
+
+        unsigned int end = buffer->out_len;
+        buffer->move_to (mark);
+
+        if (buffer->idx < buffer->len && !before)
+          buffer->copy_glyph ();
+        /* TODO We ignore KashidaLike setting. */
+        for (unsigned int i = 0; i < count; i++)
+          buffer->output_glyph (glyphs[i]);
+        if (buffer->idx < buffer->len && !before)
+          buffer->skip_glyph ();
+
+        buffer->move_to (end + count);
+
+        buffer->unsafe_to_break_from_outbuffer (mark, MIN (buffer->idx + 1, buffer->len));
+      }
+
+      if (flags & SetMark)
+        mark = mark_loc;
+
+      if (entry.data.currentInsertIndex != 0xFFFF)
+      {
+        unsigned int count = (flags & CurrentInsertCount) >> 5;
+        unsigned int start = entry.data.currentInsertIndex;
+        const GlyphID *glyphs = &insertionAction[start];
+        if (unlikely (!c->sanitizer.check_array (glyphs, count))) count = 0;
+
+        bool before = flags & CurrentInsertBefore;
+
+        unsigned int end = buffer->out_len;
+
+        if (buffer->idx < buffer->len && !before)
+          buffer->copy_glyph ();
+        /* TODO We ignore KashidaLike setting. */
+        for (unsigned int i = 0; i < count; i++)
+          buffer->output_glyph (glyphs[i]);
+        if (buffer->idx < buffer->len && !before)
+          buffer->skip_glyph ();
+
+        /* Humm. Not sure where to move to.  There's this wording under
+         * DontAdvance flag:
+         *
+         * "If set, don't update the glyph index before going to the new state.
+         * This does not mean that the glyph pointed to is the same one as
+         * before. If you've made insertions immediately downstream of the
+         * current glyph, the next glyph processed would in fact be the first
+         * one inserted."
+         *
+         * This suggests that if DontAdvance is NOT set, we should move to
+         * end+count.  If it *was*, then move to end, such that newly inserted
+         * glyphs are now visible.
+         *
+         * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417
+         */
+        buffer->move_to ((flags & DontAdvance) ? end : end + count);
+      }
+    }
+
+    public:
+    bool ret;
+    private:
+    hb_aat_apply_context_t *c;
+    unsigned int mark;
+    const UnsizedArrayOf<GlyphID> &insertionAction;
+  };
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    driver_context_t dc (this, c);
+
+    StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
+    driver.drive (&dc);
+
+    return_trace (dc.ret);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* The rest of array sanitizations are done at run-time. */
+    return_trace (c->check_struct (this) && machine.sanitize (c) &&
+                  insertionAction);
+  }
+
+  protected:
+  StateTable<Types, EntryData>
+                machine;
+  NNOffsetTo<UnsizedArrayOf<GlyphID>, HBUINT>
+                insertionAction;        /* Byte offset from stateHeader to the start of
+                                         * the insertion glyph table. */
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+
+struct Feature
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16      featureType;    /* The type of feature. */
+  HBUINT16      featureSetting; /* The feature's setting (aka selector). */
+  HBUINT32      enableFlags;    /* Flags for the settings that this feature
+                                 * and setting enables. */
+  HBUINT32      disableFlags;   /* Complement of flags for the settings that this
+                                 * feature and setting disable. */
+
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+template <typename Types>
+struct ChainSubtable
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  template <typename T>
+  friend struct Chain;
+
+  unsigned int get_size () const     { return length; }
+  unsigned int get_type () const     { return coverage & 0xFF; }
+  unsigned int get_coverage () const { return coverage >> (sizeof (HBUINT) * 8 - 8); }
+
+  enum Coverage
+  {
+    Vertical            = 0x80, /* If set, this subtable will only be applied
+                                 * to vertical text. If clear, this subtable
+                                 * will only be applied to horizontal text. */
+    Backwards           = 0x40, /* If set, this subtable will process glyphs
+                                 * in descending order. If clear, it will
+                                 * process the glyphs in ascending order. */
+    AllDirections       = 0x20, /* If set, this subtable will be applied to
+                                 * both horizontal and vertical text (i.e.
+                                 * the state of bit 0x80000000 is ignored). */
+    Logical             = 0x10, /* If set, this subtable will process glyphs
+                                 * in logical order (or reverse logical order,
+                                 * depending on the value of bit 0x80000000). */
+  };
+  enum Type
+  {
+    Rearrangement       = 0,
+    Contextual          = 1,
+    Ligature            = 2,
+    Noncontextual       = 4,
+    Insertion           = 5
+  };
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case Rearrangement:         return_trace (c->dispatch (u.rearrangement));
+    case Contextual:            return_trace (c->dispatch (u.contextual));
+    case Ligature:              return_trace (c->dispatch (u.ligature));
+    case Noncontextual:         return_trace (c->dispatch (u.noncontextual));
+    case Insertion:             return_trace (c->dispatch (u.insertion));
+    default:                    return_trace (c->default_return_value ());
+    }
+  }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    hb_sanitize_with_object_t with (&c->sanitizer, this);
+    return_trace (dispatch (c));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!length.sanitize (c) ||
+        length <= min_size ||
+        !c->check_range (this, length))
+      return_trace (false);
+
+    hb_sanitize_with_object_t with (c, this);
+    return_trace (dispatch (c));
+  }
+
+  protected:
+  HBUINT        length;         /* Total subtable length, including this header. */
+  HBUINT        coverage;       /* Coverage flags and subtable type. */
+  HBUINT32      subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
+  union {
+  RearrangementSubtable<Types>  rearrangement;
+  ContextualSubtable<Types>     contextual;
+  LigatureSubtable<Types>       ligature;
+  NoncontextualSubtable<Types>  noncontextual;
+  InsertionSubtable<Types>      insertion;
+  } u;
+  public:
+  DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4);
+};
+
+template <typename Types>
+struct Chain
+{
+  typedef typename Types::HBUINT HBUINT;
+
+  hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
+  {
+    hb_mask_t flags = defaultFlags;
+    {
+      unsigned int count = featureCount;
+      for (unsigned i = 0; i < count; i++)
+      {
+        const Feature &feature = featureZ[i];
+        hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType;
+        hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting;
+      retry:
+        const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
+        if (info && info->setting == setting)
+        {
+          flags &= feature.disableFlags;
+          flags |= feature.enableFlags;
+        }
+        else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE && setting == HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS)
+        {
+          /* Deprecated. https://github.com/harfbuzz/harfbuzz/issues/1342 */
+          type = HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE;
+          setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS;
+          goto retry;
+        }
+      }
+    }
+    return flags;
+  }
+
+  void apply (hb_aat_apply_context_t *c,
+                     hb_mask_t flags) const
+  {
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
+    unsigned int count = subtableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      bool reverse;
+
+      if (!(subtable->subFeatureFlags & flags))
+        goto skip;
+
+      if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
+          HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
+          bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical))
+        goto skip;
+
+      /* Buffer contents is always in logical direction.  Determine if
+       * we need to reverse before applying this subtable.  We reverse
+       * back after if we did reverse indeed.
+       *
+       * Quoting the spac:
+       * """
+       * Bits 28 and 30 of the coverage field control the order in which
+       * glyphs are processed when the subtable is run by the layout engine.
+       * Bit 28 is used to indicate if the glyph processing direction is
+       * the same as logical order or layout order. Bit 30 is used to
+       * indicate whether glyphs are processed forwards or backwards within
+       * that order.
+
+                Bit 30  Bit 28  Interpretation for Horizontal Text
+                0       0       The subtable is processed in layout order
+                                (the same order as the glyphs, which is
+                                always left-to-right).
+                1       0       The subtable is processed in reverse layout order
+                                (the order opposite that of the glyphs, which is
+                                always right-to-left).
+                0       1       The subtable is processed in logical order
+                                (the same order as the characters, which may be
+                                left-to-right or right-to-left).
+                1       1       The subtable is processed in reverse logical order
+                                (the order opposite that of the characters, which
+                                may be right-to-left or left-to-right).
+       */
+      reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ?
+                bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) :
+                bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) !=
+                HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
+
+      if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
+        goto skip;
+
+      if (reverse)
+        c->buffer->reverse ();
+
+      subtable->apply (c);
+
+      if (reverse)
+        c->buffer->reverse ();
+
+      (void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index);
+
+      if (unlikely (!c->buffer->successful)) return;
+
+    skip:
+      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
+      c->set_lookup_index (c->lookup_index + 1);
+    }
+  }
+
+  unsigned int get_size () const { return length; }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
+  {
+    TRACE_SANITIZE (this);
+    if (!length.sanitize (c) ||
+        length < min_size ||
+        !c->check_range (this, length))
+      return_trace (false);
+
+    if (!c->check_array (featureZ.arrayZ, featureCount))
+      return_trace (false);
+
+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
+    unsigned int count = subtableCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (!subtable->sanitize (c))
+        return_trace (false);
+      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
+    }
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT32      defaultFlags;   /* The default specification for subtables. */
+  HBUINT32      length;         /* Total byte count, including this header. */
+  HBUINT        featureCount;   /* Number of feature subtable entries. */
+  HBUINT        subtableCount;  /* The number of subtables in the chain. */
+
+  UnsizedArrayOf<Feature>       featureZ;       /* Features. */
+/*ChainSubtable firstSubtable;*//* Subtables. */
+/*subtableGlyphCoverageArray*/  /* Only if version >= 3. We don't use. */
+
+  public:
+  DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT));
+};
+
+
+/*
+ * The 'mort'/'morx' Table
+ */
+
+template <typename Types>
+struct mortmorx
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_morx;
+
+  bool has_data () const { return version != 0; }
+
+  void compile_flags (const hb_aat_map_builder_t *mapper,
+                      hb_aat_map_t *map) const
+  {
+    const Chain<Types> *chain = &firstChain;
+    unsigned int count = chainCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      map->chain_flags.push (chain->compile_flags (mapper));
+      chain = &StructAfter<Chain<Types> > (*chain);
+    }
+  }
+
+  void apply (hb_aat_apply_context_t *c) const
+  {
+    if (unlikely (!c->buffer->successful)) return;
+    c->set_lookup_index (0);
+    const Chain<Types> *chain = &firstChain;
+    unsigned int count = chainCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      chain->apply (c, c->plan->aat_map.chain_flags[i]);
+      if (unlikely (!c->buffer->successful)) return;
+      chain = &StructAfter<Chain<Types> > (*chain);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!version.sanitize (c) || !version || !chainCount.sanitize (c))
+      return_trace (false);
+
+    const Chain<Types> *chain = &firstChain;
+    unsigned int count = chainCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (!chain->sanitize (c, version))
+        return_trace (false);
+      chain = &StructAfter<Chain<Types> > (*chain);
+    }
+
+    return_trace (true);
+  }
+
+  protected:
+  HBUINT16      version;        /* Version number of the glyph metamorphosis table.
+                                 * 1, 2, or 3. */
+  HBUINT16      unused;         /* Set to 0. */
+  HBUINT32      chainCount;     /* Number of metamorphosis chains contained in this
+                                 * table. */
+  Chain<Types>  firstChain;     /* Chains. */
+
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct morx : mortmorx<ExtendedTypes>
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_morx;
+};
+struct mort : mortmorx<ObsoleteTypes>
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_mort;
+};
+
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_MORX_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout-trak-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,237 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_TRAK_TABLE_HH
+#define HB_AAT_LAYOUT_TRAK_TABLE_HH
+
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
+
+/*
+ * trak -- Tracking
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html
+ */
+#define HB_AAT_TAG_trak HB_TAG('t','r','a','k')
+
+
+namespace AAT {
+
+
+struct TrackTableEntry
+{
+  friend struct TrackData;
+
+  float get_track_value () const { return track.to_float (); }
+
+  int get_value (const void *base, unsigned int index,
+                 unsigned int table_size) const
+  { return (base+valuesZ).as_array (table_size)[index]; }
+
+  public:
+  bool sanitize (hb_sanitize_context_t *c, const void *base,
+                 unsigned int table_size) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (valuesZ.sanitize (c, base, table_size))));
+  }
+
+  protected:
+  Fixed         track;          /* Track value for this record. */
+  NameID        trackNameID;    /* The 'name' table index for this track.
+                                 * (a short word or phrase like "loose"
+                                 * or "very tight") */
+  NNOffsetTo<UnsizedArrayOf<FWORD> >
+                valuesZ;        /* Offset from start of tracking table to
+                                 * per-size tracking values for this track. */
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct TrackData
+{
+  float interpolate_at (unsigned int idx,
+                        float target_size,
+                        const TrackTableEntry &trackTableEntry,
+                        const void *base) const
+  {
+    unsigned int sizes = nSizes;
+    hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
+
+    float s0 = size_table[idx].to_float ();
+    float s1 = size_table[idx + 1].to_float ();
+    float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
+    return t * trackTableEntry.get_value (base, idx + 1, sizes) +
+           (1.f - t) * trackTableEntry.get_value (base, idx, sizes);
+  }
+
+  int get_tracking (const void *base, float ptem) const
+  {
+    /* CoreText points are CSS pixels (96 per inch),
+     * NOT typographic points (72 per inch).
+     *
+     * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
+     */
+    float csspx = ptem * 96.f / 72.f;
+
+    /*
+     * Choose track.
+     */
+    const TrackTableEntry *trackTableEntry = nullptr;
+    unsigned int count = nTracks;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      /* Note: Seems like the track entries are sorted by values.  But the
+       * spec doesn't explicitly say that.  It just mentions it in the example. */
+
+      /* For now we only seek for track entries with zero tracking value */
+
+      if (trackTable[i].get_track_value () == 0.f)
+      {
+        trackTableEntry = &trackTable[i];
+        break;
+      }
+    }
+    if (!trackTableEntry) return 0.;
+
+    /*
+     * Choose size.
+     */
+    unsigned int sizes = nSizes;
+    if (!sizes) return 0.;
+    if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
+
+    hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
+    unsigned int size_index;
+    for (size_index = 0; size_index < sizes - 1; size_index++)
+      if (size_table[size_index].to_float () >= csspx)
+        break;
+
+    return round (interpolate_at (size_index ? size_index - 1 : 0, csspx,
+                                  *trackTableEntry, base));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          sizeTable.sanitize (c, base, nSizes) &&
+                          trackTable.sanitize (c, nTracks, base, nSizes)));
+  }
+
+  protected:
+  HBUINT16      nTracks;        /* Number of separate tracks included in this table. */
+  HBUINT16      nSizes;         /* Number of point sizes included in this table. */
+  LOffsetTo<UnsizedArrayOf<Fixed>, false>
+                sizeTable;      /* Offset from start of the tracking table to
+                                 * Array[nSizes] of size values.. */
+  UnsizedArrayOf<TrackTableEntry>
+                trackTable;     /* Array[nTracks] of TrackTableEntry records. */
+
+  public:
+  DEFINE_SIZE_ARRAY (8, trackTable);
+};
+
+struct trak
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_trak;
+
+  bool has_data () const { return version.to_int (); }
+
+  bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    hb_mask_t trak_mask = c->plan->trak_mask;
+
+    const float ptem = c->font->ptem;
+    if (unlikely (ptem <= 0.f))
+      return_trace (false);
+
+    hb_buffer_t *buffer = c->buffer;
+    if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
+    {
+      const TrackData &trackData = this+horizData;
+      int tracking = trackData.get_tracking (this, ptem);
+      hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2);
+      hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
+      foreach_grapheme (buffer, start, end)
+      {
+        if (!(buffer->info[start].mask & trak_mask)) continue;
+        buffer->pos[start].x_advance += advance_to_add;
+        buffer->pos[start].x_offset += offset_to_add;
+      }
+    }
+    else
+    {
+      const TrackData &trackData = this+vertData;
+      int tracking = trackData.get_tracking (this, ptem);
+      hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2);
+      hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
+      foreach_grapheme (buffer, start, end)
+      {
+        if (!(buffer->info[start].mask & trak_mask)) continue;
+        buffer->pos[start].y_advance += advance_to_add;
+        buffer->pos[start].y_offset += offset_to_add;
+      }
+    }
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) &&
+                          version.major == 1 &&
+                          horizData.sanitize (c, this, this) &&
+                          vertData.sanitize (c, this, this)));
+  }
+
+  protected:
+  FixedVersion<>version;        /* Version of the tracking table
+                                         * (0x00010000u for version 1.0). */
+  HBUINT16      format;         /* Format of the tracking table (set to 0). */
+  OffsetTo<TrackData>
+                horizData;      /* Offset from start of tracking table to TrackData
+                                 * for horizontal text (or 0 if none). */
+  OffsetTo<TrackData>
+                vertData;       /* Offset from start of tracking table to TrackData
+                                 * for vertical text (or 0 if none). */
+  HBUINT16      reserved;       /* Reserved. Set to 0. */
+
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_TRAK_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,384 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-open-type.hh"
+
+#include "hb-ot-face.hh"
+#include "hb-aat-layout.hh"
+#include "hb-aat-fdsc-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-aat-layout-ankr-table.hh"
+#include "hb-aat-layout-bsln-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-aat-layout-feat-table.hh"
+#include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-aat-layout-kerx-table.hh"
+#include "hb-aat-layout-morx-table.hh"
+#include "hb-aat-layout-trak-table.hh"
+#include "hb-aat-ltag-table.hh"
+
+
+/**
+ * SECTION:hb-aat-layout
+ * @title: hb-aat-layout
+ * @short_description: Apple Advanced Typography Layout
+ * @include: hb-aat.h
+ *
+ * Functions for querying OpenType Layout features in the font face.
+ **/
+
+
+/* Table data courtesy of Apple.  Converted from mnemonics to integers
+ * when moving to this file. */
+static const hb_aat_feature_mapping_t feature_mappings[] =
+{
+  {HB_TAG ('a','f','r','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS,               HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS,             HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
+  {HB_TAG ('c','2','p','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS,         HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
+  {HB_TAG ('c','2','s','c'), HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS,          HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE},
+  {HB_TAG ('c','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF},
+  {HB_TAG ('c','a','s','e'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT,   HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF},
+  {HB_TAG ('c','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF},
+  {HB_TAG ('c','p','s','p'), HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT,   HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF},
+  {HB_TAG ('c','s','w','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF},
+  {HB_TAG ('d','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON,              HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF},
+  {HB_TAG ('e','x','p','t'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS,              (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS,               HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS,             HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
+  {HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT,                (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT,            (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
+  {HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA,          HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF},
+  {HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
+  {HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION,         HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL,                HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION},
+  {HB_TAG ('h','o','j','o'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS,                (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('h','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT,                (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('i','t','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN,        HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF},
+  {HB_TAG ('j','p','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','7','8'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','8','3'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('j','p','9','0'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS,             (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('l','i','g','a'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES,               HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF},
+  {HB_TAG ('l','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE,             HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS,             (hb_aat_layout_feature_selector_t) 2},
+  {HB_TAG ('m','g','r','k'), HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS,     HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF},
+  {HB_TAG ('n','l','c','k'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS,                  (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('o','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE,             HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS,             (hb_aat_layout_feature_selector_t) 2},
+  {HB_TAG ('o','r','d','n'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS,                       HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('p','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('p','c','a','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS,         HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
+  {HB_TAG ('p','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,              (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,          HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS,           (hb_aat_layout_feature_selector_t) 4},
+  {HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT,              (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT,             (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA,               HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON,                   HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
+  {HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS,           HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE,              HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS,          HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
+  {HB_TAG ('s','m','p','l'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS,          (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('s','s','0','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF},
+  {HB_TAG ('s','s','0','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF},
+  {HB_TAG ('s','s','0','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF},
+  {HB_TAG ('s','s','0','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF},
+  {HB_TAG ('s','s','0','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF},
+  {HB_TAG ('s','s','0','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF},
+  {HB_TAG ('s','s','0','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF},
+  {HB_TAG ('s','s','0','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF},
+  {HB_TAG ('s','s','0','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON,          HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF},
+  {HB_TAG ('s','s','1','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON,           HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF},
+  {HB_TAG ('s','s','1','1'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF},
+  {HB_TAG ('s','s','1','2'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF},
+  {HB_TAG ('s','s','1','3'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF},
+  {HB_TAG ('s','s','1','4'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF},
+  {HB_TAG ('s','s','1','5'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF},
+  {HB_TAG ('s','s','1','6'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON,       HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF},
+  {HB_TAG ('s','s','1','7'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON,     HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF},
+  {HB_TAG ('s','s','1','8'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF},
+  {HB_TAG ('s','s','1','9'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON,      HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF},
+  {HB_TAG ('s','s','2','0'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES,  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON,        HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF},
+  {HB_TAG ('s','u','b','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS,                      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','u','p','s'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION,       HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS,                      HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
+  {HB_TAG ('s','w','s','h'), HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES, HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON,            HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF},
+  {HB_TAG ('t','i','t','l'), HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS,           HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS,                   HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS},
+  {HB_TAG ('t','n','a','m'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS,   (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('t','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING,          HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS,             (hb_aat_layout_feature_selector_t) 4},
+  {HB_TAG ('t','r','a','d'), HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE,         HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS,         (hb_aat_layout_feature_selector_t) 16},
+  {HB_TAG ('t','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT,               (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('u','n','i','c'), HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE,             (hb_aat_layout_feature_selector_t) 14,                 (hb_aat_layout_feature_selector_t) 15},
+  {HB_TAG ('v','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('v','e','r','t'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
+  {HB_TAG ('v','h','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT,            (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA,          HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON,         HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF},
+  {HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
+  {HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
+  {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS,      HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON,                HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
+};
+
+const hb_aat_feature_mapping_t *
+hb_aat_layout_find_feature_mapping (hb_tag_t tag)
+{
+  return (const hb_aat_feature_mapping_t *) bsearch (&tag,
+                                                     feature_mappings,
+                                                     ARRAY_LENGTH (feature_mappings),
+                                                     sizeof (feature_mappings[0]),
+                                                     hb_aat_feature_mapping_t::cmp);
+}
+
+
+/*
+ * hb_aat_apply_context_t
+ */
+
+AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
+                                                     hb_font_t *font_,
+                                                     hb_buffer_t *buffer_,
+                                                     hb_blob_t *blob) :
+                                                       plan (plan_),
+                                                       font (font_),
+                                                       face (font->face),
+                                                       buffer (buffer_),
+                                                       sanitizer (),
+                                                       ankr_table (&Null(AAT::ankr)),
+                                                       lookup_index (0),
+                                                       debug_depth (0)
+{
+  sanitizer.init (blob);
+  sanitizer.set_num_glyphs (face->get_num_glyphs ());
+  sanitizer.start_processing ();
+  sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
+}
+
+AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t ()
+{ sanitizer.end_processing (); }
+
+void
+AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
+{ ankr_table = ankr_table_; }
+
+
+/*
+ * mort/morx/kerx/trak
+ */
+
+
+void
+hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
+                           hb_aat_map_t *map)
+{
+  const AAT::morx& morx = *mapper->face->table.morx;
+  if (morx.has_data ())
+  {
+    morx.compile_flags (mapper, map);
+    return;
+  }
+
+  const AAT::mort& mort = *mapper->face->table.mort;
+  if (mort.has_data ())
+  {
+    mort.compile_flags (mapper, map);
+    return;
+  }
+}
+
+
+/*
+ * hb_aat_layout_has_substitution:
+ * @face:
+ *
+ * Returns:
+ * Since: 2.3.0
+ */
+hb_bool_t
+hb_aat_layout_has_substitution (hb_face_t *face)
+{
+  return face->table.morx->has_data () ||
+         face->table.mort->has_data ();
+}
+
+void
+hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
+                          hb_font_t *font,
+                          hb_buffer_t *buffer)
+{
+  hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
+  const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
+  if (morx.has_data ())
+  {
+    AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
+    morx.apply (&c);
+    return;
+  }
+
+  hb_blob_t *mort_blob = font->face->table.mort.get_blob ();
+  const AAT::mort& mort = *mort_blob->as<AAT::mort> ();
+  if (mort.has_data ())
+  {
+    AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
+    mort.apply (&c);
+    return;
+  }
+}
+
+void
+hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
+{
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
+  for (unsigned int i = 0; i < count; i++)
+    if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
+      pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
+}
+
+static bool
+is_deleted_glyph (const hb_glyph_info_t *info)
+{
+  return info->codepoint == AAT::DELETED_GLYPH;
+}
+
+void
+hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
+{
+  hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
+}
+
+/*
+ * hb_aat_layout_has_positioning:
+ * @face:
+ *
+ * Returns:
+ * Since: 2.3.0
+ */
+hb_bool_t
+hb_aat_layout_has_positioning (hb_face_t *face)
+{
+  return face->table.kerx->has_data ();
+}
+
+void
+hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
+                        hb_font_t *font,
+                        hb_buffer_t *buffer)
+{
+  hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
+  const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
+
+  AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
+  c.set_ankr_table (font->face->table.ankr.get ());
+  kerx.apply (&c);
+}
+
+
+/*
+ * hb_aat_layout_has_tracking:
+ * @face:
+ *
+ * Returns:
+ * Since: 2.3.0
+ */
+hb_bool_t
+hb_aat_layout_has_tracking (hb_face_t *face)
+{
+  return face->table.trak->has_data ();
+}
+
+void
+hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
+                     hb_font_t *font,
+                     hb_buffer_t *buffer)
+{
+  const AAT::trak& trak = *font->face->table.trak;
+
+  AAT::hb_aat_apply_context_t c (plan, font, buffer);
+  trak.apply (&c);
+}
+
+
+hb_language_t
+_hb_aat_language_get (hb_face_t *face,
+                      unsigned int i)
+{
+  return face->table.ltag->get_language (i);
+}
+
+/**
+ * hb_aat_layout_get_feature_types:
+ * @face: a face object
+ * @start_offset: iteration's start offset
+ * @feature_count:(inout) (allow-none): buffer size as input, filled size as output
+ * @features: (out caller-allocates) (array length=feature_count): features buffer
+ *
+ * Return value: Number of all available feature types.
+ *
+ * Since: 2.2.0
+ */
+unsigned int
+hb_aat_layout_get_feature_types (hb_face_t                    *face,
+                                 unsigned int                  start_offset,
+                                 unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
+                                 hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */)
+{
+  return face->table.feat->get_feature_types (start_offset, feature_count, features);
+}
+
+/**
+ * hb_aat_layout_feature_type_get_name_id:
+ * @face: a face object
+ * @feature_type: feature id
+ *
+ * Return value: Name ID index
+ *
+ * Since: 2.2.0
+ */
+hb_ot_name_id_t
+hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
+                                        hb_aat_layout_feature_type_t  feature_type)
+{
+  return face->table.feat->get_feature_name_id (feature_type);
+}
+
+/**
+ * hb_aat_layout_feature_type_get_selectors:
+ * @face:    a face object
+ * @feature_type: feature id
+ * @start_offset:    iteration's start offset
+ * @selector_count: (inout) (allow-none): buffer size as input, filled size as output
+ * @selectors: (out caller-allocates) (array length=selector_count): settings buffer
+ * @default_index: (out) (allow-none): index of default selector if any
+ *
+ * If upon return, @default_index is set to #HB_AAT_LAYOUT_NO_SELECTOR_INDEX, then
+ * the feature type is non-exclusive.  Otherwise, @default_index is the index of
+ * the selector that is selected by default.
+ *
+ * Return value: Number of all available feature selectors.
+ *
+ * Since: 2.2.0
+ */
+unsigned int
+hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
+                                               hb_aat_layout_feature_type_t           feature_type,
+                                               unsigned int                           start_offset,
+                                               unsigned int                          *selector_count, /* IN/OUT.  May be NULL. */
+                                               hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
+                                               unsigned int                          *default_index   /* OUT.     May be NULL. */)
+{
+  return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.h	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,486 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_H_IN
+#error "Include <hb-aat.h> instead."
+#endif
+
+#ifndef HB_AAT_LAYOUT_H
+#define HB_AAT_LAYOUT_H
+
+#include "hb.h"
+
+#include "hb-ot.h"
+
+HB_BEGIN_DECLS
+
+/**
+ * hb_aat_layout_feature_type_t:
+ *
+ *
+ * Since: 2.2.0
+ */
+typedef enum
+{
+  HB_AAT_LAYOUT_FEATURE_TYPE_INVALID                            = 0xFFFF,
+
+  HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC                    = 0,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES                          = 1,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION                 = 2,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE                        = 3,
+  HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION              = 4,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT           = 5,
+  HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING                     = 6,
+  HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE                   = 8,
+  HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE                    = 9,
+  HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION                  = 10,
+  HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS                          = 11,
+  HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE        = 13,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS                 = 14,
+  HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS                = 15,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE                 = 16,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES             = 17,
+  HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE             = 18,
+  HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS                      = 19,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE                    = 20,
+  HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE                        = 21,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING                       = 22,
+  HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION                    = 23,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE                    = 24,
+  HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE                  = 25,
+  HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE           = 26,
+  HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE         = 27,
+  HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA                          = 28,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE       = 29,
+  HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE      = 30,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE  = 31,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN                   = 32,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT              = 33,
+  HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA                     = 34,
+  HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES             = 35,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES            = 36,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE                         = 37,
+  HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE                         = 38,
+  HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE                  = 39,
+  HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE             = 103,
+
+  _HB_AAT_LAYOUT_FEATURE_TYPE_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
+} hb_aat_layout_feature_type_t;
+
+/**
+ * hb_aat_layout_feature_selector_t:
+ *
+ *
+ * Since: 2.2.0
+ */
+typedef enum
+{
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVALID                        = 0xFFFF,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_ON           = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_TYPE_FEATURES_OFF          = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON          = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_ON            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMMON_LIGATURES_OFF           = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_ON              = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RARE_LIGATURES_OFF             = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_ON                       = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOGOS_OFF                      = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_ON              = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_REBUS_PICTURES_OFF             = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_ON         = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIPHTHONG_LIGATURES_OFF        = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_ON           = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SQUARED_LIGATURES_OFF          = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_ON    = 14,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ABBREV_SQUARED_LIGATURES_OFF   = 15,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_ON            = 16,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SYMBOL_LIGATURES_OFF           = 17,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_ON        = 18,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_LIGATURES_OFF       = 19,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON        = 20,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF       = 21,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UNCONNECTED                    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PARTIALLY_CONNECTED            = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CURSIVE                        = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_AND_LOWER_CASE           = 0, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_CAPS                       = 1, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALL_LOWER_CASE                 = 2, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMALL_CAPS                     = 3, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS                   = 4, /* deprecated */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INITIAL_CAPS_AND_SMALL_CAPS    = 5, /* deprecated */
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF  = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_ON    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINGUISTIC_REARRANGEMENT_OFF   = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_NUMBERS             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS           = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_NUMBERS            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_NUMBERS          = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_ON        = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_INITIAL_SWASHES_OFF       = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_ON          = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_WORD_FINAL_SWASHES_OFF         = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_ON        = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_INITIAL_SWASHES_OFF       = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_ON          = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LINE_FINAL_SWASHES_OFF         = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_ON           = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NON_FINAL_SWASHES_OFF          = 9,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SHOW_DIACRITICS                = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HIDE_DIACRITICS                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DECOMPOSE_DIACRITICS           = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION                = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SUPERIORS                      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INFERIORS                      = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ORDINALS                       = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS           = 4,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS                   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_VERTICAL_FRACTIONS             = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS             = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_ON             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PREVENT_OVERLAP_OFF            = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_ON          = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHENS_TO_EM_DASH_OFF         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_ON           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_EN_DASH_OFF          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON                = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF               = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_ON            = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FORM_INTERROBANG_OFF           = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_ON                = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SMART_QUOTES_OFF               = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_ON         = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIODS_TO_ELLIPSIS_OFF        = 11,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_ON             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HYPHEN_TO_MINUS_OFF            = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_ON        = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ASTERISK_TO_MULTIPLY_OFF       = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_ON             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASH_TO_DIVIDE_OFF            = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_ON        = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INEQUALITY_LIGATURES_OFF       = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_ON                   = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPONENTS_OFF                  = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_ON          = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATHEMATICAL_GREEK_OFF         = 11,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ORNAMENTS                   = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DINGBATS                       = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PI_CHARACTERS                  = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FLEURONS                       = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DECORATIVE_BORDERS             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INTERNATIONAL_SYMBOLS          = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MATH_SYMBOLS                   = 6,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ALTERNATES                  = 0,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL1                  = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL2                  = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL3                  = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL4                  = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DESIGN_LEVEL5                  = 4,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLE_OPTIONS               = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DISPLAY_TEXT                   = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ENGRAVED_TEXT                  = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ILLUMINATED_CAPS               = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TITLING_CAPS                   = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TALL_CAPS                      = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_CHARACTERS         = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SIMPLIFIED_CHARACTERS          = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1978_CHARACTERS             = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1983_CHARACTERS             = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS1990_CHARACTERS             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_ONE            = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_TWO            = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_THREE          = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FOUR           = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_ALT_FIVE           = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_EXPERT_CHARACTERS              = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_JIS2004_CHARACTERS             = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HOJO_CHARACTERS                = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NLCCHARACTERS                  = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRADITIONAL_NAMES_CHARACTERS   = 14,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_NUMBERS             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_NUMBERS             = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT              = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_TEXT                = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_THIRD_WIDTH_TEXT               = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT             = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT          = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT            = 6,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL                = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HIRAGANA_TO_KATAKANA           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_KATAKANA_TO_HIRAGANA           = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_KANA_TO_ROMANIZATION           = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_HIRAGANA       = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMANIZATION_TO_KATAKANA       = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_ONE        = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_TWO        = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL_ALT_THREE      = 9,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_ANNOTATION                  = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_BOX_ANNOTATION                 = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROUNDED_BOX_ANNOTATION         = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CIRCLE_ANNOTATION              = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_CIRCLE_ANNOTATION     = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PARENTHESIS_ANNOTATION         = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PERIOD_ANNOTATION              = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ROMAN_NUMERAL_ANNOTATION       = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAMOND_ANNOTATION             = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_BOX_ANNOTATION        = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_INVERTED_ROUNDED_BOX_ANNOTATION= 10,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_KANA                = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_KANA              = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_IDEOGRAPHS          = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_IDEOGRAPHS        = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_IDEOGRAPHS          = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_ON       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CANONICAL_COMPOSITION_OFF      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_ON   = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_COMPATIBILITY_COMPOSITION_OFF  = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_ON     = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_TRANSCODING_COMPOSITION_OFF    = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_RUBY_KANA                   = 0, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA                      = 1, /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON                   = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF                  = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_SYMBOL_ALTERNATIVES     = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_ONE             = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_TWO             = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_THREE           = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FOUR            = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_SYMBOL_ALT_FIVE            = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_IDEOGRAPHIC_ALTERNATIVES    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_ONE            = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_TWO            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_THREE          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FOUR           = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_IDEOGRAPHIC_ALT_FIVE           = 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_CENTERED    = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_VERTICAL_ROMAN_HBASELINE   = 1,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_CJK_ITALIC_ROMAN            = 0,    /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN               = 1,    /* deprecated - use HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON instead */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_ON            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CJK_ITALIC_ROMAN_OFF           = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_ON       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_LAYOUT_OFF      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_ON      = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CASE_SENSITIVE_SPACING_OFF     = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON        = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF       = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON         = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF        = 3,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_STYLISTIC_ALTERNATES        = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_ON           = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ONE_OFF          = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_ON           = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWO_OFF          = 5,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_ON         = 6,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THREE_OFF        = 7,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_ON          = 8,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOUR_OFF         = 9,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_ON          = 10,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIVE_OFF         = 11,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_ON           = 12,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIX_OFF          = 13,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_ON         = 14,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVEN_OFF        = 15,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_ON         = 16,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHT_OFF        = 17,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_ON          = 18,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINE_OFF         = 19,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_ON           = 20,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TEN_OFF          = 21,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_ON        = 22,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_ELEVEN_OFF       = 23,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_ON        = 24,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWELVE_OFF       = 25,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_ON      = 26,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_THIRTEEN_OFF     = 27,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_ON      = 28,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FOURTEEN_OFF     = 29,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_ON       = 30,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_FIFTEEN_OFF      = 31,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_ON       = 32,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SIXTEEN_OFF      = 33,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_ON     = 34,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_SEVENTEEN_OFF    = 35,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_ON      = 36,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_EIGHTEEN_OFF     = 37,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_ON      = 38,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_NINETEEN_OFF     = 39,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_ON        = 40,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_STYLISTIC_ALT_TWENTY_OFF       = 41,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_ON       = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_ALTERNATES_OFF      = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_ON            = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_SWASH_ALTERNATES_OFF           = 3,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_ON = 4,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_CONTEXTUAL_SWASH_ALTERNATES_OFF= 5,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS          = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_PETITE_CAPS         = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_UPPER_CASE             = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_SMALL_CAPS          = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_UPPER_CASE_PETITE_CAPS         = 2,
+
+  /* Selectors for #HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE */
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_HALF_WIDTH_CJK_ROMAN           = 0,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_CJK_ROMAN         = 1,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_CJK_ROMAN              = 2,
+  HB_AAT_LAYOUT_FEATURE_SELECTOR_FULL_WIDTH_CJK_ROMAN           = 3,
+
+  _HB_AAT_LAYOUT_FEATURE_SELECTOR_MAX_VALUE= 0x7FFFFFFFu, /*< skip >*/
+} hb_aat_layout_feature_selector_t;
+
+HB_EXTERN unsigned int
+hb_aat_layout_get_feature_types (hb_face_t                    *face,
+                                 unsigned int                  start_offset,
+                                 unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
+                                 hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */);
+
+HB_EXTERN hb_ot_name_id_t
+hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
+                                        hb_aat_layout_feature_type_t  feature_type);
+
+typedef struct hb_aat_layout_feature_selector_info_t
+{
+  hb_ot_name_id_t                       name_id;
+  hb_aat_layout_feature_selector_t      enable;
+  hb_aat_layout_feature_selector_t      disable;
+  /*< private >*/
+  unsigned int                          reserved;
+} hb_aat_layout_feature_selector_info_t;
+
+#define HB_AAT_LAYOUT_NO_SELECTOR_INDEX         0xFFFFu
+
+HB_EXTERN unsigned int
+hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
+                                               hb_aat_layout_feature_type_t           feature_type,
+                                               unsigned int                           start_offset,
+                                               unsigned int                          *selector_count, /* IN/OUT.  May be NULL. */
+                                               hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
+                                               unsigned int                          *default_index   /* OUT.     May be NULL. */);
+
+
+/*
+ * morx/mort
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_substitution (hb_face_t *face);
+
+
+/*
+ * kerx
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_positioning (hb_face_t *face);
+
+
+/*
+ * trak
+ */
+
+HB_EXTERN hb_bool_t
+hb_aat_layout_has_tracking (hb_face_t *face);
+
+
+HB_END_DECLS
+
+#endif /* HB_AAT_LAYOUT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-layout.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_HH
+#define HB_AAT_LAYOUT_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape.hh"
+
+
+struct hb_aat_feature_mapping_t
+{
+  hb_tag_t otFeatureTag;
+  hb_aat_layout_feature_type_t aatFeatureType;
+  hb_aat_layout_feature_selector_t selectorToEnable;
+  hb_aat_layout_feature_selector_t selectorToDisable;
+
+  static int cmp (const void *key_, const void *entry_)
+  {
+    hb_tag_t key = * (unsigned int *) key_;
+    const hb_aat_feature_mapping_t * entry = (const hb_aat_feature_mapping_t *) entry_;
+    return key < entry->otFeatureTag ? -1 :
+           key > entry->otFeatureTag ? 1 :
+           0;
+  }
+};
+
+HB_INTERNAL const hb_aat_feature_mapping_t *
+hb_aat_layout_find_feature_mapping (hb_tag_t tag);
+
+HB_INTERNAL void
+hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
+                           hb_aat_map_t *map);
+
+HB_INTERNAL void
+hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
+                          hb_font_t *font,
+                          hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
+                        hb_font_t *font,
+                        hb_buffer_t *buffer);
+
+HB_INTERNAL void
+hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
+                     hb_font_t *font,
+                     hb_buffer_t *buffer);
+
+HB_INTERNAL hb_language_t
+_hb_aat_language_get (hb_face_t *face,
+                      unsigned int i);
+
+
+#endif /* HB_AAT_LAYOUT_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-ltag-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_LTAG_TABLE_HH
+#define HB_AAT_LTAG_TABLE_HH
+
+#include "hb-open-type.hh"
+
+/*
+ * ltag -- Language Tag
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html
+ */
+#define HB_AAT_TAG_ltag HB_TAG('l','t','a','g')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+struct FTStringRange
+{
+  friend struct ltag;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && (base+tag).sanitize (c, length));
+  }
+
+  protected:
+  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
+                tag;            /* Offset from the start of the table to
+                                 * the beginning of the string */
+  HBUINT16      length;         /* String length (in bytes) */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct ltag
+{
+  static constexpr hb_tag_t tableTag = HB_AAT_TAG_ltag;
+
+  hb_language_t get_language (unsigned int i) const
+  {
+    const FTStringRange &range = tagRanges[i];
+    return hb_language_from_string ((const char *) (this+range.tag).arrayZ,
+                                    range.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version >= 1 &&
+                          tagRanges.sanitize (c, this)));
+  }
+
+  protected:
+  HBUINT32      version;        /* Table version; currently 1 */
+  HBUINT32      flags;          /* Table flags; currently none defined */
+  LArrayOf<FTStringRange>
+                tagRanges;      /* Range for each tag's string */
+  public:
+  DEFINE_SIZE_ARRAY (12, tagRanges);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LTAG_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-map.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2010,2011,2013  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-aat-map.hh"
+
+#include "hb-aat-layout.hh"
+
+
+void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
+                                        unsigned int value)
+{
+  if (tag == HB_TAG ('a','a','l','t'))
+  {
+    feature_info_t *info = features.push();
+    info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
+    info->setting = (hb_aat_layout_feature_selector_t) value;
+    return;
+  }
+
+  const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
+  if (!mapping) return;
+
+  feature_info_t *info = features.push();
+  info->type = mapping->aatFeatureType;
+  info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
+}
+
+void
+hb_aat_map_builder_t::compile (hb_aat_map_t  &m)
+{
+  /* Sort features and merge duplicates */
+  if (features.length)
+  {
+    features.qsort ();
+    unsigned int j = 0;
+    for (unsigned int i = 1; i < features.length; i++)
+      if (features[i].type != features[j].type)
+        features[++j] = features[i];
+    features.shrink (j + 1);
+  }
+
+  hb_aat_layout_compile_map (this, &m);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat-map.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_MAP_HH
+#define HB_AAT_MAP_HH
+
+#include "hb.hh"
+
+
+struct hb_aat_map_t
+{
+  friend struct hb_aat_map_builder_t;
+
+  public:
+
+  void init ()
+  {
+    memset (this, 0, sizeof (*this));
+    chain_flags.init ();
+  }
+  void fini () { chain_flags.fini (); }
+
+  public:
+  hb_vector_t<hb_mask_t> chain_flags;
+};
+
+struct hb_aat_map_builder_t
+{
+  public:
+
+  HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_,
+                                    const hb_segment_properties_t *props_ HB_UNUSED) :
+                                      face (face_) {}
+
+  HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);
+
+  HB_INTERNAL void compile (hb_aat_map_t  &m);
+
+  public:
+  struct feature_info_t
+  {
+    hb_aat_layout_feature_type_t  type;
+    hb_aat_layout_feature_selector_t  setting;
+    unsigned  seq; /* For stable sorting only. */
+
+    static int cmp (const void *pa, const void *pb)
+    {
+      const feature_info_t *a = (const feature_info_t *) pa;
+      const feature_info_t *b = (const feature_info_t *) pb;
+      return (a->type != b->type) ? (a->type < b->type ? -1 : 1) :
+             (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
+    }
+
+    int cmp (hb_aat_layout_feature_type_t ty) const
+    {
+      return (type != ty) ? (type < ty ? -1 : 1) : 0;
+    }
+  };
+
+  public:
+  hb_face_t *face;
+
+  public:
+  hb_vector_t<feature_info_t> features;
+};
+
+
+#endif /* HB_AAT_MAP_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-aat.h	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_AAT_H
+#define HB_AAT_H
+#define HB_AAT_H_IN
+
+#include "hb.h"
+
+#include "hb-aat-layout.h"
+
+HB_BEGIN_DECLS
+
+HB_END_DECLS
+
+#undef HB_AAT_H_IN
+#endif /* HB_AAT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-array.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,277 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ARRAY_HH
+#define HB_ARRAY_HH
+
+#include "hb.hh"
+#include "hb-dsalgs.hh"
+#include "hb-iter.hh"
+#include "hb-null.hh"
+
+
+template <typename Type>
+struct hb_sorted_array_t;
+
+template <typename Type>
+struct hb_array_t :
+        hb_iter_t<hb_array_t<Type>, Type>,
+        hb_iter_mixin_t<hb_array_t<Type>, Type>
+{
+  /*
+   * Constructors.
+   */
+  hb_array_t () : arrayZ (nullptr), length (0) {}
+  hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
+  template <unsigned int length_> hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
+
+
+  /*
+   * Iterator implementation.
+   */
+  typedef Type __item_type__;
+  Type& __item_at__ (unsigned i) const
+  {
+    if (unlikely (i >= length)) return CrapOrNull (Type);
+    return arrayZ[i];
+  }
+  void __forward__ (unsigned n)
+  {
+    if (unlikely (n > length))
+      n = length;
+    length -= n;
+    arrayZ += n;
+  }
+  void __rewind__ (unsigned n)
+  {
+    if (unlikely (n > length))
+      n = length;
+    length -= n;
+  }
+  unsigned __len__ () const { return length; }
+  bool __random_access__ () const { return true; }
+
+  /* Extra operators.
+   */
+  Type * operator & () const { return arrayZ; }
+  operator hb_array_t<const Type> () { return hb_array_t<const Type> (arrayZ, length); }
+  template <typename T> operator T * () const { return arrayZ; }
+
+  /*
+   * Compare, Sort, and Search.
+   */
+
+  /* Note: our compare is NOT lexicographic; it also does NOT call Type::cmp. */
+  int cmp (const hb_array_t<Type> &a) const
+  {
+    if (length != a.length)
+      return (int) a.length - (int) length;
+    return hb_memcmp (a.arrayZ, arrayZ, get_size ());
+  }
+  static int cmp (const void *pa, const void *pb)
+  {
+    hb_array_t<Type> *a = (hb_array_t<Type> *) pa;
+    hb_array_t<Type> *b = (hb_array_t<Type> *) pb;
+    return b->cmp (*a);
+  }
+
+  template <typename T>
+  Type *lsearch (const T &x, Type *not_found = nullptr)
+  {
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!this->arrayZ[i].cmp (x))
+        return &this->arrayZ[i];
+    return not_found;
+  }
+  template <typename T>
+  const Type *lsearch (const T &x, const Type *not_found = nullptr) const
+  {
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!this->arrayZ[i].cmp (x))
+        return &this->arrayZ[i];
+    return not_found;
+  }
+
+  hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
+  {
+    if (likely (length))
+      ::qsort (arrayZ, length, this->item_size, cmp_);
+    return hb_sorted_array_t<Type> (*this);
+  }
+  hb_sorted_array_t<Type> qsort ()
+  {
+    if (likely (length))
+      ::qsort (arrayZ, length, this->item_size, Type::cmp);
+    return hb_sorted_array_t<Type> (*this);
+  }
+  void qsort (unsigned int start, unsigned int end)
+  {
+    end = MIN (end, length);
+    assert (start <= end);
+    if (likely (start < end))
+      ::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
+  }
+
+  /*
+   * Other methods.
+   */
+
+  unsigned int get_size () const { return length * this->item_size; }
+
+  hb_array_t<Type> sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
+  {
+    if (!start_offset && !seg_count)
+      return *this;
+
+    unsigned int count = length;
+    if (unlikely (start_offset > count))
+      count = 0;
+    else
+      count -= start_offset;
+    if (seg_count)
+      count = *seg_count = MIN (count, *seg_count);
+    return hb_array_t<Type> (arrayZ + start_offset, count);
+  }
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
+  { return sub_array (start_offset, &seg_count); }
+
+  /* Only call if you allocated the underlying array using malloc() or similar. */
+  void free ()
+  { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
+
+  template <typename hb_sanitize_context_t>
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return c->check_array (arrayZ, length); }
+
+  /*
+   * Members
+   */
+
+  public:
+  Type *arrayZ;
+  unsigned int length;
+};
+template <typename T> inline hb_array_t<T>
+hb_array (T *array, unsigned int length)
+{ return hb_array_t<T> (array, length); }
+template <typename T, unsigned int length_> inline hb_array_t<T>
+hb_array (T (&array_)[length_])
+{ return hb_array_t<T> (array_); }
+
+
+enum hb_bfind_not_found_t
+{
+  HB_BFIND_NOT_FOUND_DONT_STORE,
+  HB_BFIND_NOT_FOUND_STORE,
+  HB_BFIND_NOT_FOUND_STORE_CLOSEST,
+};
+
+template <typename Type>
+struct hb_sorted_array_t :
+        hb_sorted_iter_t<hb_sorted_array_t<Type>, Type>,
+        hb_array_t<Type>,
+        hb_iter_mixin_t<hb_sorted_array_t<Type>, Type>
+{
+  hb_sorted_array_t () : hb_array_t<Type> () {}
+  hb_sorted_array_t (const hb_array_t<Type> &o) : hb_array_t<Type> (o) {}
+  hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
+  template <unsigned int length_> hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
+
+  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
+  { return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
+  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
+  { return sub_array (start_offset, &seg_count); }
+
+  template <typename T>
+  Type *bsearch (const T &x, Type *not_found = nullptr)
+  {
+    unsigned int i;
+    return bfind (x, &i) ? &this->arrayZ[i] : not_found;
+  }
+  template <typename T>
+  const Type *bsearch (const T &x, const Type *not_found = nullptr) const
+  {
+    unsigned int i;
+    return bfind (x, &i) ? &this->arrayZ[i] : not_found;
+  }
+  template <typename T>
+  bool bfind (const T &x, unsigned int *i = nullptr,
+                     hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                     unsigned int to_store = (unsigned int) -1) const
+  {
+    int min = 0, max = (int) this->length - 1;
+    const Type *array = this->arrayZ;
+    while (min <= max)
+    {
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      int c = array[mid].cmp (x);
+      if (c < 0)
+        max = mid - 1;
+      else if (c > 0)
+        min = mid + 1;
+      else
+      {
+        if (i)
+          *i = mid;
+        return true;
+      }
+    }
+    if (i)
+    {
+      switch (not_found)
+      {
+        case HB_BFIND_NOT_FOUND_DONT_STORE:
+          break;
+
+        case HB_BFIND_NOT_FOUND_STORE:
+          *i = to_store;
+          break;
+
+        case HB_BFIND_NOT_FOUND_STORE_CLOSEST:
+          if (max < 0 || (max < (int) this->length && array[max].cmp (x) > 0))
+            max++;
+          *i = max;
+          break;
+      }
+    }
+    return false;
+  }
+};
+template <typename T> inline hb_sorted_array_t<T>
+hb_sorted_array (T *array, unsigned int length)
+{ return hb_sorted_array_t<T> (array, length); }
+template <typename T, unsigned int length_> inline hb_sorted_array_t<T>
+hb_sorted_array (T (&array_)[length_])
+{ return hb_sorted_array_t<T> (array_); }
+
+
+typedef hb_array_t<const char> hb_bytes_t;
+typedef hb_array_t<const unsigned char> hb_ubytes_t;
+
+
+#endif /* HB_ARRAY_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Contributor(s):
- *      Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_ATOMIC_PRIVATE_HH
-#define HB_ATOMIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* atomic_int */
-
-/* We need external help for these */
-
-#if defined(hb_atomic_int_impl_add) \
- && defined(hb_atomic_ptr_impl_get) \
- && defined(hb_atomic_ptr_impl_cmpexch)
-
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_atomic_int_impl_t as well. */
-
-
-#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
-
-#include <windows.h>
-
-/* MinGW has a convoluted history of supporting MemoryBarrier
- * properly.  As such, define a function to wrap the whole
- * thing. */
-static inline void _HBMemoryBarrier (void) {
-#if !defined(MemoryBarrier)
-  long dummy = 0;
-  InterlockedExchange (&dummy, 1);
-#else
-  MemoryBarrier ();
-#endif
-}
-
-typedef LONG hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           InterlockedExchangeAdd (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)               (_HBMemoryBarrier (), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           __sync_fetch_and_add (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)               (void *) (__sync_synchronize (), *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       __sync_bool_compare_and_swap ((P), (O), (N))
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
-
-#include <atomic.h>
-#include <mbarrier.h>
-
-typedef unsigned int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           ( ({__machine_rw_barrier ();}), atomic_add_int_nv (&(AI), (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)               ( ({__machine_rw_barrier ();}), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       ( ({__machine_rw_barrier ();}), atomic_cas_ptr ((void **) (P), (void *) (O), (void *) (N)) == (void *) (O) ? true : false)
-
-
-#elif !defined(HB_NO_MT) && defined(__APPLE__)
-
-#include <libkern/OSAtomic.h>
-#ifdef __MAC_OS_X_MIN_REQUIRED
-#include <AvailabilityMacros.h>
-#elif defined(__IPHONE_OS_MIN_REQUIRED)
-#include <Availability.h>
-#endif
-
-
-typedef int32_t hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)               (OSMemoryBarrier (), (void *) *(P))
-#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
-#else
-#if __ppc64__ || __x86_64__ || __aarch64__
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwap64Barrier ((int64_t) (void *) (O), (int64_t) (void *) (N), (int64_t*) (P))
-#else
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwap32Barrier ((int32_t) (void *) (O), (int32_t) (void *) (N), (int32_t*) (P))
-#endif
-#endif
-
-
-#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))
-
-#include <builtins.h>
-
-
-static inline int _hb_fetch_and_add(volatile int* AI, unsigned int V) {
-  __lwsync();
-  int result = __fetch_and_add(AI, V);
-  __isync();
-  return result;
-}
-static inline int _hb_compare_and_swaplp(volatile long* P, long O, long N) {
-  __sync();
-  int result = __compare_and_swaplp (P, &O, N);
-  __sync();
-  return result;
-}
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add (&(AI), (V))
-
-#define hb_atomic_ptr_impl_get(P)               (__sync(), (void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swaplp ((long*)(P), (long)(O), (long)(N))
-
-#elif !defined(HB_NO_MT)
-
-#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
-
-typedef volatile int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           (((AI) += (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)               ((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
-
-
-#else /* HB_NO_MT */
-
-typedef int hb_atomic_int_impl_t;
-#define hb_atomic_int_impl_add(AI, V)           (((AI) += (V)) - (V))
-
-#define hb_atomic_ptr_impl_get(P)               ((void *) *(P))
-#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
-
-
-#endif
-
-
-#define HB_ATOMIC_INT_INIT(V)          {V}
-
-struct hb_atomic_int_t
-{
-  hb_atomic_int_impl_t v;
-
-  inline void set_unsafe (int v_) { v = v_; }
-  inline int get_unsafe (void) const { return v; }
-  inline int inc (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v),  1); }
-  inline int dec (void) { return hb_atomic_int_impl_add (const_cast<hb_atomic_int_impl_t &> (v), -1); }
-};
-
-
-#define hb_atomic_ptr_get(P) hb_atomic_ptr_impl_get(P)
-#define hb_atomic_ptr_cmpexch(P,O,N) hb_atomic_ptr_impl_cmpexch((P),(O),(N))
-
-
-#endif /* HB_ATOMIC_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-atomic.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,300 @@
+/*
+ * Copyright © 2007  Chris Wilson
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Contributor(s):
+ *      Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ATOMIC_HH
+#define HB_ATOMIC_HH
+
+#include "hb.hh"
+
+
+/*
+ * Atomic integers and pointers.
+ */
+
+
+/* We need external help for these */
+
+#if defined(hb_atomic_int_impl_add) \
+ && defined(hb_atomic_ptr_impl_get) \
+ && defined(hb_atomic_ptr_impl_cmpexch)
+
+/* Defined externally, i.e. in config.h. */
+
+
+#elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE)
+
+/* C++11-style GCC primitives. */
+
+#define _hb_memory_barrier()                    __sync_synchronize ()
+
+#define hb_atomic_int_impl_add(AI, V)           __atomic_fetch_add ((AI), (V), __ATOMIC_ACQ_REL)
+#define hb_atomic_int_impl_set_relaxed(AI, V)   __atomic_store_n ((AI), (V), __ATOMIC_RELAXED)
+#define hb_atomic_int_impl_set(AI, V)           __atomic_store_n ((AI), (V), __ATOMIC_RELEASE)
+#define hb_atomic_int_impl_get_relaxed(AI)      __atomic_load_n ((AI), __ATOMIC_RELAXED)
+#define hb_atomic_int_impl_get(AI)              __atomic_load_n ((AI), __ATOMIC_ACQUIRE)
+
+#define hb_atomic_ptr_impl_set_relaxed(P, V)    __atomic_store_n ((P), (V), __ATOMIC_RELAXED)
+#define hb_atomic_ptr_impl_get_relaxed(P)       __atomic_load_n ((P), __ATOMIC_RELAXED)
+#define hb_atomic_ptr_impl_get(P)               __atomic_load_n ((P), __ATOMIC_ACQUIRE)
+static inline bool
+_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+{
+  const void *O = O_; // Need lvalue
+  return __atomic_compare_exchange_n ((void **) P, (void **) &O, (void *) N, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
+
+#elif !defined(HB_NO_MT) && __cplusplus >= 201103L
+
+/* C++11 atomics. */
+
+#include <atomic>
+
+#define _hb_memory_barrier()                    std::atomic_thread_fence(std::memory_order_ack_rel)
+#define _hb_memory_r_barrier()                  std::atomic_thread_fence(std::memory_order_acquire)
+#define _hb_memory_w_barrier()                  std::atomic_thread_fence(std::memory_order_release)
+
+#define hb_atomic_int_impl_add(AI, V)           (reinterpret_cast<std::atomic<int> *> (AI)->fetch_add ((V), std::memory_order_acq_rel))
+#define hb_atomic_int_impl_set_relaxed(AI, V)   (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_int_impl_set(AI, V)           (reinterpret_cast<std::atomic<int> *> (AI)->store ((V), std::memory_order_release))
+#define hb_atomic_int_impl_get_relaxed(AI)      (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_relaxed))
+#define hb_atomic_int_impl_get(AI)              (reinterpret_cast<std::atomic<int> *> (AI)->load (std::memory_order_acquire))
+
+#define hb_atomic_ptr_impl_set_relaxed(P, V)    (reinterpret_cast<std::atomic<void*> *> (P)->store ((V), std::memory_order_relaxed))
+#define hb_atomic_ptr_impl_get_relaxed(P)       (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_relaxed))
+#define hb_atomic_ptr_impl_get(P)               (reinterpret_cast<std::atomic<void*> *> (P)->load (std::memory_order_acquire))
+static inline bool
+_hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
+{
+  const void *O = O_; // Need lvalue
+  return reinterpret_cast<std::atomic<const void*> *> (P)->compare_exchange_weak (O, N, std::memory_order_acq_rel, std::memory_order_relaxed);
+}
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(_WIN32)
+
+#include <windows.h>
+
+static inline void _hb_memory_barrier ()
+{
+#if !defined(MemoryBarrier)
+  /* MinGW has a convoluted history of supporting MemoryBarrier. */
+  LONG dummy = 0;
+  InterlockedExchange (&dummy, 1);
+#else
+  MemoryBarrier ();
+#endif
+}
+#define _hb_memory_barrier()                    _hb_memory_barrier ()
+
+#define hb_atomic_int_impl_add(AI, V)           InterlockedExchangeAdd ((LONG *) (AI), (V))
+static_assert ((sizeof (LONG) == sizeof (int)), "");
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (InterlockedCompareExchangePointer ((P), (N), (O)) == (O))
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
+
+#define _hb_memory_barrier()                    __sync_synchronize ()
+
+#define hb_atomic_int_impl_add(AI, V)           __sync_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       __sync_bool_compare_and_swap ((P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS)
+
+#include <atomic.h>
+#include <mbarrier.h>
+
+#define _hb_memory_r_barrier()                  __machine_r_barrier ()
+#define _hb_memory_w_barrier()                  __machine_w_barrier ()
+#define _hb_memory_barrier()                    __machine_rw_barrier ()
+
+static inline int _hb_fetch_and_add (int *AI, int V)
+{
+  _hb_memory_w_barrier ();
+  int result = atomic_add_int_nv ((uint_t *) AI, V) - V;
+  _hb_memory_r_barrier ();
+  return result;
+}
+static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N)
+{
+  _hb_memory_w_barrier ();
+  bool result = atomic_cas_ptr (P, O, N) == O;
+  _hb_memory_r_barrier ();
+  return result;
+}
+
+#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swap_ptr ((P), (O), (N))
+
+
+#elif !defined(HB_NO_MT) && defined(__APPLE__)
+
+#include <libkern/OSAtomic.h>
+#ifdef __MAC_OS_X_MIN_REQUIRED
+#include <AvailabilityMacros.h>
+#elif defined(__IPHONE_OS_MIN_REQUIRED)
+#include <Availability.h>
+#endif
+
+#define _hb_memory_barrier()                    OSMemoryBarrier ()
+
+#define hb_atomic_int_impl_add(AI, V)           (OSAtomicAdd32Barrier ((V), (AI)) - (V))
+
+#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100)
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwapPtrBarrier ((O), (N), (P))
+#else
+#if __ppc64__ || __x86_64__ || __aarch64__
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P))
+#else
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P))
+#endif
+#endif
+
+
+#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__))
+
+#include <builtins.h>
+
+#define _hb_memory_barrier()                    __lwsync ()
+
+static inline int _hb_fetch_and_add (int *AI, int V)
+{
+  _hb_memory_barrier ();
+  int result = __fetch_and_add (AI, V);
+  _hb_memory_barrier ();
+  return result;
+}
+static inline bool _hb_compare_and_swaplp (long *P, long O, long N)
+{
+  _hb_memory_barrier ();
+  bool result = __compare_and_swaplp (P, &O, N);
+  _hb_memory_barrier ();
+  return result;
+}
+
+#define hb_atomic_int_impl_add(AI, V)           _hb_fetch_and_add ((AI), (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
+static_assert ((sizeof (long) == sizeof (void *)), "");
+
+
+#elif !defined(HB_NO_MT)
+
+#define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
+
+#define _hb_memory_barrier()
+
+#define hb_atomic_int_impl_add(AI, V)           ((*(AI) += (V)) - (V))
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+
+
+#else /* HB_NO_MT */
+
+#define hb_atomic_int_impl_add(AI, V)           ((*(AI) += (V)) - (V))
+
+#define _hb_memory_barrier()
+
+#define hb_atomic_ptr_impl_cmpexch(P,O,N)       (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+
+
+#endif
+
+
+#ifndef _hb_memory_r_barrier
+#define _hb_memory_r_barrier()                  _hb_memory_barrier ()
+#endif
+#ifndef _hb_memory_w_barrier
+#define _hb_memory_w_barrier()                  _hb_memory_barrier ()
+#endif
+#ifndef hb_atomic_int_impl_set_relaxed
+#define hb_atomic_int_impl_set_relaxed(AI, V)   (*(AI) = (V))
+#endif
+#ifndef hb_atomic_int_impl_get_relaxed
+#define hb_atomic_int_impl_get_relaxed(AI)      (*(AI))
+#endif
+
+#ifndef hb_atomic_ptr_impl_set_relaxed
+#define hb_atomic_ptr_impl_set_relaxed(P, V)    (*(P) = (V))
+#endif
+#ifndef hb_atomic_ptr_impl_get_relaxed
+#define hb_atomic_ptr_impl_get_relaxed(P)       (*(P))
+#endif
+#ifndef hb_atomic_int_impl_set
+inline void hb_atomic_int_impl_set (int *AI, int v)     { _hb_memory_w_barrier (); *AI = v; }
+#endif
+#ifndef hb_atomic_int_impl_get
+inline int hb_atomic_int_impl_get (const int *AI)       { int v = *AI; _hb_memory_r_barrier (); return v; }
+#endif
+#ifndef hb_atomic_ptr_impl_get
+inline void *hb_atomic_ptr_impl_get (void ** const P)   { void *v = *P; _hb_memory_r_barrier (); return v; }
+#endif
+
+
+#define HB_ATOMIC_INT_INIT(V)          {V}
+struct hb_atomic_int_t
+{
+  void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); }
+  void set (int v_) { hb_atomic_int_impl_set (&v, v_); }
+  int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); }
+  int get () const { return hb_atomic_int_impl_get (&v); }
+  int inc () { return hb_atomic_int_impl_add (&v,  1); }
+  int dec () { return hb_atomic_int_impl_add (&v, -1); }
+
+  int v;
+};
+
+
+#define HB_ATOMIC_PTR_INIT(V)          {V}
+template <typename P>
+struct hb_atomic_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  void init (T* v_ = nullptr) { set_relaxed (v_); }
+  void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
+  T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
+  T *get () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
+  bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
+
+  T * operator -> () const                    { return get (); }
+  template <typename C> operator C * () const { return get (); }
+
+  T *v;
+};
+
+
+#endif /* HB_ATOMIC_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BLOB_PRIVATE_HH
-#define HB_BLOB_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-
-
-/*
- * hb_blob_t
- */
-
-struct hb_blob_t
-{
-  inline void fini_shallow (void)
-  {
-    destroy_user_data ();
-  }
-
-  inline void destroy_user_data (void)
-  {
-    if (destroy)
-    {
-      destroy (user_data);
-      user_data = nullptr;
-      destroy = nullptr;
-    }
-  }
-
-  HB_INTERNAL bool try_make_writable (void);
-  HB_INTERNAL bool try_make_writable_inplace (void);
-  HB_INTERNAL bool try_make_writable_inplace_unix (void);
-
-  inline void lock (void)
-  {
-    hb_blob_make_immutable (this);
-  }
-
-  template <typename Type>
-  inline const Type* as (void) const
-  {
-    return unlikely (!data) ? &Null(Type) : reinterpret_cast<const Type *> (data);
-  }
-
-  public:
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  bool immutable;
-
-  const char *data;
-  unsigned int length;
-  hb_memory_mode_t mode;
-
-  void *user_data;
-  hb_destroy_func_t destroy;
-};
-
-
-#endif /* HB_BLOB_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -25,14 +25,20 @@
  * Red Hat Author(s): Behdad Esfahbod
  */
 
-/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1308
+ * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
+ * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html
+ */
 #ifndef _POSIX_C_SOURCE
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 #define _POSIX_C_SOURCE 200809L
+#pragma GCC diagnostic pop
 #endif
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-blob-private.hh"
+#include "hb.hh"
+#include "hb-blob.hh"
 
 #ifdef HAVE_SYS_MMAN_H
 #ifdef HAVE_UNISTD_H
@@ -47,6 +53,19 @@
 
 
 /**
+ * SECTION: hb-blob
+ * @title: hb-blob
+ * @short_description: Binary data containers
+ * @include: hb.h
+ *
+ * Blobs wrap a chunk of binary data to handle lifecycle management of data
+ * while it is passed between client and HarfBuzz.  Blobs are primarily used
+ * to create font faces, but also to access font face tables, as well as
+ * pass around other binary data.
+ **/
+
+
+/**
  * hb_blob_create: (skip)
  * @data: Pointer to blob data.
  * @length: Length of @data in bytes.
@@ -130,7 +149,7 @@
 {
   hb_blob_t *blob;
 
-  if (!length || offset >= parent->length)
+  if (!length || !parent || offset >= parent->length)
     return hb_blob_get_empty ();
 
   hb_blob_make_immutable (parent);
@@ -181,22 +200,9 @@
  * Since: 0.9.2
  **/
 hb_blob_t *
-hb_blob_get_empty (void)
+hb_blob_get_empty ()
 {
-  static const hb_blob_t _hb_blob_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* data */
-    0, /* length */
-    HB_MEMORY_MODE_READONLY, /* mode */
-
-    nullptr, /* user_data */
-    nullptr  /* destroy */
-  };
-
-  return const_cast<hb_blob_t *> (&_hb_blob_nil);
+  return const_cast<hb_blob_t *> (&Null(hb_blob_t));
 }
 
 /**
@@ -291,10 +297,10 @@
 void
 hb_blob_make_immutable (hb_blob_t *blob)
 {
-  if (hb_object_is_inert (blob))
+  if (hb_object_is_immutable (blob))
     return;
 
-  blob->immutable = true;
+  hb_object_make_immutable (blob);
 }
 
 /**
@@ -310,7 +316,7 @@
 hb_bool_t
 hb_blob_is_immutable (hb_blob_t *blob)
 {
-  return blob->immutable;
+  return hb_object_is_immutable (blob);
 }
 
 
@@ -384,7 +390,7 @@
 
 
 bool
-hb_blob_t::try_make_writable_inplace_unix (void)
+hb_blob_t::try_make_writable_inplace_unix ()
 {
 #if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT)
   uintptr_t pagesize = -1, mask, length;
@@ -427,7 +433,7 @@
 }
 
 bool
-hb_blob_t::try_make_writable_inplace (void)
+hb_blob_t::try_make_writable_inplace ()
 {
   DEBUG_MSG_FUNC (BLOB, this, "making writable inplace\n");
 
@@ -442,9 +448,9 @@
 }
 
 bool
-hb_blob_t::try_make_writable (void)
+hb_blob_t::try_make_writable ()
 {
-  if (this->immutable)
+  if (hb_object_is_immutable (this))
     return false;
 
   if (this->mode == HB_MEMORY_MODE_WRITABLE)
@@ -487,11 +493,11 @@
 # include <fcntl.h>
 #endif
 
-#if defined(_WIN32) || defined(__CYGWIN__)
+#ifdef _WIN32
 # include <windows.h>
 #else
-# ifndef _O_BINARY
-#  define _O_BINARY 0
+# ifndef O_BINARY
+#  define O_BINARY 0
 # endif
 #endif
 
@@ -503,17 +509,19 @@
 {
   char *contents;
   unsigned long length;
-#if defined(_WIN32) || defined(__CYGWIN__)
+#ifdef _WIN32
   HANDLE mapping;
 #endif
 };
 
+#if (defined(HAVE_MMAP) || defined(_WIN32)) && !defined(HB_NO_MMAP)
 static void
-_hb_mapped_file_destroy (hb_mapped_file_t *file)
+_hb_mapped_file_destroy (void *file_)
 {
+  hb_mapped_file_t *file = (hb_mapped_file_t *) file_;
 #ifdef HAVE_MMAP
   munmap (file->contents, file->length);
-#elif defined(_WIN32) || defined(__CYGWIN__)
+#elif defined(_WIN32)
   UnmapViewOfFile (file->contents);
   CloseHandle (file->mapping);
 #else
@@ -522,6 +530,7 @@
 
   free (file);
 }
+#endif
 
 /**
  * hb_blob_create_from_file:
@@ -540,7 +549,7 @@
   hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
   if (unlikely (!file)) return hb_blob_get_empty ();
 
-  int fd = open (file_name, O_RDONLY | _O_BINARY, 0);
+  int fd = open (file_name, O_RDONLY | O_BINARY, 0);
   if (unlikely (fd == -1)) goto fail_without_close;
 
   struct stat st;
@@ -563,21 +572,54 @@
 fail_without_close:
   free (file);
 
-#elif (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_MMAP)
+#elif defined(_WIN32) && !defined(HB_NO_MMAP)
   hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t));
   if (unlikely (!file)) return hb_blob_get_empty ();
 
-  HANDLE fd = CreateFile (file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
-                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
-                          nullptr);
+  HANDLE fd;
+  unsigned int size = strlen (file_name) + 1;
+  wchar_t * wchar_file_name = (wchar_t *) malloc (sizeof (wchar_t) * size);
+  if (unlikely (wchar_file_name == nullptr)) goto fail_without_close;
+  mbstowcs (wchar_file_name, file_name, size);
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  {
+    CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 };
+    ceparams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
+    ceparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFFF;
+    ceparams.dwFileFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0xFFF00000;
+    ceparams.dwSecurityQosFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED & 0x000F0000;
+    ceparams.lpSecurityAttributes = nullptr;
+    ceparams.hTemplateFile = nullptr;
+    fd = CreateFile2 (wchar_file_name, GENERIC_READ, FILE_SHARE_READ,
+                      OPEN_EXISTING, &ceparams);
+  }
+#else
+  fd = CreateFileW (wchar_file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
+                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
+                    nullptr);
+#endif
+  free (wchar_file_name);
 
   if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
 
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  {
+    LARGE_INTEGER length;
+    GetFileSizeEx (fd, &length);
+    file->length = length.LowPart;
+    file->mapping = CreateFileMappingFromApp (fd, nullptr, PAGE_READONLY, length.QuadPart, nullptr);
+  }
+#else
   file->length = (unsigned long) GetFileSize (fd, nullptr);
   file->mapping = CreateFileMapping (fd, nullptr, PAGE_READONLY, 0, 0, nullptr);
+#endif
   if (unlikely (file->mapping == nullptr)) goto fail;
 
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+  file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0);
+#else
   file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
+#endif
   if (unlikely (file->contents == nullptr)) goto fail;
 
   CloseHandle (fd);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-blob.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,101 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BLOB_HH
+#define HB_BLOB_HH
+
+#include "hb.hh"
+
+
+/*
+ * hb_blob_t
+ */
+
+struct hb_blob_t
+{
+  void fini_shallow () { destroy_user_data (); }
+
+  void destroy_user_data ()
+  {
+    if (destroy)
+    {
+      destroy (user_data);
+      user_data = nullptr;
+      destroy = nullptr;
+    }
+  }
+
+  HB_INTERNAL bool try_make_writable ();
+  HB_INTERNAL bool try_make_writable_inplace ();
+  HB_INTERNAL bool try_make_writable_inplace_unix ();
+
+  template <typename Type>
+  const Type* as () const
+  {
+    return length < hb_null_size (Type) ? &Null(Type) : reinterpret_cast<const Type *> (data);
+  }
+  hb_bytes_t as_bytes () const
+  { return hb_bytes_t (data, length); }
+
+  public:
+  hb_object_header_t header;
+
+  const char *data;
+  unsigned int length;
+  hb_memory_mode_t mode;
+
+  void *user_data;
+  hb_destroy_func_t destroy;
+};
+
+
+/*
+ * hb_blob_ptr_t
+ */
+
+template <typename P>
+struct hb_blob_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {}
+  hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; }
+  const T * operator -> () const { return get (); }
+  const T & operator * () const  { return *get (); }
+  template <typename C> operator const C * () const { return get (); }
+  operator const char * () const { return (const char *) get (); }
+  const T * get () const { return b->as<T> (); }
+  hb_blob_t * get_blob () const { return b.get_raw (); }
+  unsigned int get_length () const { return b.get ()->length; }
+  void destroy () { hb_blob_destroy (b.get ()); b = nullptr; }
+
+  hb_nonnull_ptr_t<hb_blob_t> b;
+};
+
+
+#endif /* HB_BLOB_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-json.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,7 +29,7 @@
 #ifndef HB_BUFFER_DESERIALIZE_JSON_HH
 #define HB_BUFFER_DESERIALIZE_JSON_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-buffer-deserialize-json.hh"
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-deserialize-text.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,7 +29,7 @@
 #ifndef HB_BUFFER_DESERIALIZE_TEXT_HH
 #define HB_BUFFER_DESERIALIZE_TEXT_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-buffer-deserialize-text.hh"
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,388 +0,0 @@
-/*
- * Copyright © 1998-2004  David Turner and Werner Lemberg
- * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_BUFFER_PRIVATE_HH
-#define HB_BUFFER_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-unicode-private.hh"
-
-
-#ifndef HB_BUFFER_MAX_LEN_FACTOR
-#define HB_BUFFER_MAX_LEN_FACTOR 32
-#endif
-#ifndef HB_BUFFER_MAX_LEN_MIN
-#define HB_BUFFER_MAX_LEN_MIN 8192
-#endif
-#ifndef HB_BUFFER_MAX_LEN_DEFAULT
-#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
-#endif
-
-#ifndef HB_BUFFER_MAX_OPS_FACTOR
-#define HB_BUFFER_MAX_OPS_FACTOR 64
-#endif
-#ifndef HB_BUFFER_MAX_OPS_MIN
-#define HB_BUFFER_MAX_OPS_MIN 1024
-#endif
-#ifndef HB_BUFFER_MAX_OPS_DEFAULT
-#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
-#endif
-
-static_assert ((sizeof (hb_glyph_info_t) == 20), "");
-static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
-
-HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
-HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
-HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
-
-enum hb_buffer_scratch_flags_t {
-  HB_BUFFER_SCRATCH_FLAG_DEFAULT                        = 0x00000000u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII                  = 0x00000001u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES         = 0x00000002u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK             = 0x00000004u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT            = 0x00000008u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK            = 0x00000010u,
-  HB_BUFFER_SCRATCH_FLAG_HAS_CGJ                        = 0x00000020u,
-
-  /* Reserved for complex shapers' internal use. */
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX0                       = 0x01000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX1                       = 0x02000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX2                       = 0x04000000u,
-  HB_BUFFER_SCRATCH_FLAG_COMPLEX3                       = 0x08000000u,
-};
-HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
-
-
-/*
- * hb_buffer_t
- */
-
-struct hb_buffer_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  /* Information about how the text in the buffer should be treated */
-  hb_unicode_funcs_t *unicode; /* Unicode functions */
-  hb_buffer_flags_t flags; /* BOT / EOT / etc. */
-  hb_buffer_cluster_level_t cluster_level;
-  hb_codepoint_t replacement; /* U+FFFD or something else. */
-  hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
-  unsigned int max_len; /* Maximum allowed len. */
-  int max_ops; /* Maximum allowed operations. */
-
-  /* Buffer contents */
-  hb_buffer_content_type_t content_type;
-  hb_segment_properties_t props; /* Script, language, direction */
-
-  bool successful; /* Allocations successful */
-  bool have_output; /* Whether we have an output buffer going on */
-  bool have_positions; /* Whether we have positions */
-
-  unsigned int idx; /* Cursor into ->info and ->pos arrays */
-  unsigned int len; /* Length of ->info and ->pos arrays */
-  unsigned int out_len; /* Length of ->out array if have_output */
-
-  unsigned int allocated; /* Length of allocated arrays */
-  hb_glyph_info_t     *info;
-  hb_glyph_info_t     *out_info;
-  hb_glyph_position_t *pos;
-
-  unsigned int serial;
-
-  /* Text before / after the main buffer contents.
-   * Always in Unicode, and ordered outward.
-   * Index 0 is for "pre-context", 1 for "post-context". */
-  static const unsigned int CONTEXT_LENGTH = 5;
-  hb_codepoint_t context[2][CONTEXT_LENGTH];
-  unsigned int context_len[2];
-
-  /* Debugging API */
-  hb_buffer_message_func_t message_func;
-  void *message_data;
-  hb_destroy_func_t message_destroy;
-
-  /* Internal debugging. */
-  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
-#ifndef HB_NDEBUG
-  uint8_t allocated_var_bits;
-#endif
-
-
-  /* Methods */
-
-  inline void allocate_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (0 == (allocated_var_bits & bits));
-    allocated_var_bits |= bits;
-#endif
-  }
-  inline void deallocate_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (bits == (allocated_var_bits & bits));
-    allocated_var_bits &= ~bits;
-#endif
-  }
-  inline void assert_var (unsigned int start, unsigned int count)
-  {
-#ifndef HB_NDEBUG
-    unsigned int end = start + count;
-    assert (end <= 8);
-    unsigned int bits = (1u<<end) - (1u<<start);
-    assert (bits == (allocated_var_bits & bits));
-#endif
-  }
-  inline void deallocate_var_all (void)
-  {
-#ifndef HB_NDEBUG
-    allocated_var_bits = 0;
-#endif
-  }
-
-  inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
-  inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
-
-  inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
-  inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
-
-  inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
-  inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
-
-  inline bool has_separate_output (void) const { return info != out_info; }
-
-
-  HB_INTERNAL void reset (void);
-  HB_INTERNAL void clear (void);
-
-  inline unsigned int backtrack_len (void) const
-  { return have_output? out_len : idx; }
-  inline unsigned int lookahead_len (void) const
-  { return len - idx; }
-  inline unsigned int next_serial (void) { return serial++; }
-
-  HB_INTERNAL void add (hb_codepoint_t  codepoint,
-                        unsigned int    cluster);
-  HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
-
-  HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
-  HB_INTERNAL void reverse (void);
-  HB_INTERNAL void reverse_clusters (void);
-  HB_INTERNAL void guess_segment_properties (void);
-
-  HB_INTERNAL void swap_buffers (void);
-  HB_INTERNAL void remove_output (void);
-  HB_INTERNAL void clear_output (void);
-  HB_INTERNAL void clear_positions (void);
-
-  HB_INTERNAL void replace_glyphs (unsigned int num_in,
-                                   unsigned int num_out,
-                                   const hb_codepoint_t *glyph_data);
-
-  HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
-  /* Makes a copy of the glyph at idx to output and replace glyph_index */
-  HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
-  HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info);
-  /* Copies glyph at idx to output but doesn't advance idx */
-  HB_INTERNAL void copy_glyph (void);
-  HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
-  /* Copies glyph at idx to output and advance idx.
-   * If there's no output, just advance idx. */
-  inline void
-  next_glyph (void)
-  {
-    if (have_output)
-    {
-      if (unlikely (out_info != info || out_len != idx)) {
-        if (unlikely (!make_room_for (1, 1))) return;
-        out_info[out_len] = info[idx];
-      }
-      out_len++;
-    }
-
-    idx++;
-  }
-
-  /* Advance idx without copying to output. */
-  inline void skip_glyph (void) { idx++; }
-
-  inline void reset_masks (hb_mask_t mask)
-  {
-    for (unsigned int j = 0; j < len; j++)
-      info[j].mask = mask;
-  }
-  inline void add_masks (hb_mask_t mask)
-  {
-    for (unsigned int j = 0; j < len; j++)
-      info[j].mask |= mask;
-  }
-  HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
-                              unsigned int cluster_start, unsigned int cluster_end);
-
-  inline void merge_clusters (unsigned int start, unsigned int end)
-  {
-    if (end - start < 2)
-      return;
-    merge_clusters_impl (start, end);
-  }
-  HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
-  HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
-  /* Merge clusters for deleting current glyph, and skip it. */
-  HB_INTERNAL void delete_glyph (void);
-
-  inline void unsafe_to_break (unsigned int start,
-                               unsigned int end)
-  {
-    if (end - start < 2)
-      return;
-    unsafe_to_break_impl (start, end);
-  }
-  HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
-  HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
-
-
-  /* Internal methods */
-  HB_INTERNAL bool enlarge (unsigned int size);
-
-  inline bool ensure (unsigned int size)
-  { return likely (!size || size < allocated) ? true : enlarge (size); }
-
-  inline bool ensure_inplace (unsigned int size)
-  { return likely (!size || size < allocated); }
-
-  HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
-  HB_INTERNAL bool shift_forward (unsigned int count);
-
-  typedef long scratch_buffer_t;
-  HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
-
-  inline void clear_context (unsigned int side) { context_len[side] = 0; }
-
-  HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
-
-  inline bool messaging (void) { return unlikely (message_func); }
-  inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
-  {
-    if (!messaging ())
-      return true;
-    va_list ap;
-    va_start (ap, fmt);
-    bool ret = message_impl (font, fmt, ap);
-    va_end (ap);
-    return ret;
-  }
-  HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
-
-  static inline void
-  set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
-  {
-    if (inf.cluster != cluster)
-    {
-      if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
-        inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-      else
-        inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-    }
-    inf.cluster = cluster;
-  }
-
-  inline int
-  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
-                                     unsigned int start, unsigned int end,
-                                     unsigned int cluster) const
-  {
-    for (unsigned int i = start; i < end; i++)
-      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
-    return cluster;
-  }
-  inline void
-  _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
-                             unsigned int start, unsigned int end,
-                             unsigned int cluster)
-  {
-    for (unsigned int i = start; i < end; i++)
-      if (cluster != infos[i].cluster)
-      {
-        scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
-        infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-      }
-  }
-
-  inline void
-  unsafe_to_break_all (void)
-  {
-    unsafe_to_break_impl (0, len);
-  }
-  inline void
-  safe_to_break_all (void)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-  }
-};
-
-
-/* Loop over clusters. Duplicated in foreach_syllable(). */
-#define foreach_cluster(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_cluster (buffer, start))
-
-static inline unsigned int
-_next_cluster (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  unsigned int cluster = info[start].cluster;
-  while (++start < count && cluster == info[start].cluster)
-    ;
-
-  return start;
-}
-
-
-#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
-  b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
-           sizeof (b->info[0].var))
-#define HB_BUFFER_ALLOCATE_VAR(b, var)          HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
-#define HB_BUFFER_DEALLOCATE_VAR(b, var)        HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
-#define HB_BUFFER_ASSERT_VAR(b, var)            HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
-
-
-#endif /* HB_BUFFER_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-serialize.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer-serialize.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-buffer-private.hh"
+#include "hb-buffer.hh"
 
 
 static const char *serialize_formats[] = {
@@ -44,7 +44,7 @@
  * Since: 0.9.7
  **/
 const char **
-hb_buffer_serialize_list_formats (void)
+hb_buffer_serialize_list_formats ()
 {
   return serialize_formats;
 }
@@ -246,7 +246,7 @@
 
     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
     {
-      if (info[i].mask &HB_GLYPH_FLAG_DEFINED)
+      if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
         p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
     }
 
@@ -440,8 +440,8 @@
 hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
                               const char *buf,
                               int buf_len, /* -1 means nul-terminated */
-                              const char **end_ptr, /* May be nullptr */
-                              hb_font_t *font, /* May be nullptr */
+                              const char **end_ptr, /* May be NULL */
+                              hb_font_t *font, /* May be NULL */
                               hb_buffer_serialize_format_t format)
 {
   const char *end;
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -27,20 +27,21 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-buffer-private.hh"
-#include "hb-utf-private.hh"
+#include "hb-buffer.hh"
+#include "hb-utf.hh"
 
 
 /**
  * SECTION: hb-buffer
- * @title: Buffers
+ * @title: hb-buffer
  * @short_description: Input and output buffers
  * @include: hb.h
  *
  * Buffers serve dual role in HarfBuzz; they hold the input characters that are
- * passed hb_shape(), and after shaping they hold the output glyphs.
+ * passed to hb_shape(), and after shaping they hold the output glyphs.
  **/
 
+
 /**
  * hb_segment_properties_equal:
  * @a: first #hb_segment_properties_t to compare.
@@ -124,14 +125,14 @@
   hb_glyph_info_t *new_info = nullptr;
   bool separate_out = out_info != info;
 
-  if (unlikely (_hb_unsigned_int_mul_overflows (size, sizeof (info[0]))))
+  if (unlikely (hb_unsigned_mul_overflows (size, sizeof (info[0]))))
     goto done;
 
   while (size >= new_allocated)
     new_allocated += (new_allocated >> 1) + 32;
 
   static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
-  if (unlikely (_hb_unsigned_int_mul_overflows (new_allocated, sizeof (info[0]))))
+  if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
     goto done;
 
   new_pos = (hb_glyph_position_t *) realloc (pos, new_allocated * sizeof (pos[0]));
@@ -182,7 +183,11 @@
   if (idx + count > len)
   {
     /* Under memory failure we might expose this area.  At least
-     * clean it up.  Oh well... */
+     * clean it up.  Oh well...
+     *
+     * Ideally, we should at least set Default_Ignorable bits on
+     * these, as well as consistent cluster values.  But the former
+     * is layering violation... */
     memset (info + len, 0, (idx + count - len) * sizeof (info[0]));
   }
   len += count;
@@ -210,23 +215,24 @@
 /* HarfBuzz-Internal API */
 
 void
-hb_buffer_t::reset (void)
+hb_buffer_t::reset ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   hb_unicode_funcs_destroy (unicode);
-  unicode = hb_unicode_funcs_get_default ();
+  unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ());
   flags = HB_BUFFER_FLAG_DEFAULT;
   replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+  invisible = 0;
 
   clear ();
 }
 
 void
-hb_buffer_t::clear (void)
+hb_buffer_t::clear ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT;
@@ -281,9 +287,9 @@
 
 
 void
-hb_buffer_t::remove_output (void)
+hb_buffer_t::remove_output ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = false;
@@ -294,9 +300,9 @@
 }
 
 void
-hb_buffer_t::clear_output (void)
+hb_buffer_t::clear_output ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = true;
@@ -307,9 +313,9 @@
 }
 
 void
-hb_buffer_t::clear_positions (void)
+hb_buffer_t::clear_positions ()
 {
-  if (unlikely (hb_object_is_inert (this)))
+  if (unlikely (hb_object_is_immutable (this)))
     return;
 
   have_output = false;
@@ -322,7 +328,7 @@
 }
 
 void
-hb_buffer_t::swap_buffers (void)
+hb_buffer_t::swap_buffers ()
 {
   if (unlikely (!successful)) return;
 
@@ -354,6 +360,8 @@
 {
   if (unlikely (!make_room_for (num_in, num_out))) return;
 
+  assert (idx + num_in <= len);
+
   merge_clusters (idx, idx + num_in);
 
   hb_glyph_info_t orig_info = info[idx];
@@ -369,37 +377,6 @@
   out_len += num_out;
 }
 
-void
-hb_buffer_t::output_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-  out_info[out_len].codepoint = glyph_index;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::output_info (const hb_glyph_info_t &glyph_info)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = glyph_info;
-
-  out_len++;
-}
-
-void
-hb_buffer_t::copy_glyph (void)
-{
-  if (unlikely (!make_room_for (0, 1))) return;
-
-  out_info[out_len] = info[idx];
-
-  out_len++;
-}
-
 bool
 hb_buffer_t::move_to (unsigned int i)
 {
@@ -429,8 +406,14 @@
     unsigned int count = out_len - i;
 
     /* This will blow in our face if memory allocation fails later
-     * in this same lookup... */
-    if (unlikely (idx < count && !shift_forward (count + 32))) return false;
+     * in this same lookup...
+     *
+     * We used to shift with extra 32 items, instead of the 0 below.
+     * But that would leave empty slots in the buffer in case of allocation
+     * failures.  Setting to zero for now to avoid other problems (see
+     * comments in shift_forward().  This can cause O(N^2) behavior more
+     * severely than adding 32 empty slots can... */
+    if (unlikely (idx < count && !shift_forward (count + 0))) return false;
 
     assert (idx >= count);
 
@@ -442,19 +425,6 @@
   return true;
 }
 
-void
-hb_buffer_t::replace_glyph (hb_codepoint_t glyph_index)
-{
-  if (unlikely (out_info != info || out_len != idx)) {
-    if (unlikely (!make_room_for (1, 1))) return;
-    out_info[out_len] = info[idx];
-  }
-  out_info[out_len].codepoint = glyph_index;
-
-  idx++;
-  out_len++;
-}
-
 
 void
 hb_buffer_t::set_masks (hb_mask_t    value,
@@ -510,7 +480,7 @@
 }
 
 void
-hb_buffer_t::reverse (void)
+hb_buffer_t::reverse ()
 {
   if (unlikely (!len))
     return;
@@ -519,7 +489,7 @@
 }
 
 void
-hb_buffer_t::reverse_clusters (void)
+hb_buffer_t::reverse_clusters ()
 {
   unsigned int i, start, count, last_cluster;
 
@@ -666,7 +636,7 @@
 }
 
 void
-hb_buffer_t::guess_segment_properties (void)
+hb_buffer_t::guess_segment_properties ()
 {
   assert (content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
           (!len && content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
@@ -701,6 +671,29 @@
 
 /* Public API */
 
+DEFINE_NULL_INSTANCE (hb_buffer_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  const_cast<hb_unicode_funcs_t *> (&_hb_Null_hb_unicode_funcs_t),
+  HB_BUFFER_FLAG_DEFAULT,
+  HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
+  HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
+  0, /* invisible */
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT,
+  HB_BUFFER_MAX_LEN_DEFAULT,
+  HB_BUFFER_MAX_OPS_DEFAULT,
+
+  HB_BUFFER_CONTENT_TYPE_INVALID,
+  HB_SEGMENT_PROPERTIES_DEFAULT,
+  false, /* successful */
+  true, /* have_output */
+  true  /* have_positions */
+
+  /* Zero is good enough for everything else. */
+};
+
+
 /**
  * hb_buffer_create: (Xconstructor)
  *
@@ -716,7 +709,7 @@
  * Since: 0.9.2
  **/
 hb_buffer_t *
-hb_buffer_create (void)
+hb_buffer_create ()
 {
   hb_buffer_t *buffer;
 
@@ -741,29 +734,9 @@
  * Since: 0.9.2
  **/
 hb_buffer_t *
-hb_buffer_get_empty (void)
+hb_buffer_get_empty ()
 {
-  static const hb_buffer_t _hb_buffer_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
-    HB_BUFFER_FLAG_DEFAULT,
-    HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
-    HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
-    HB_BUFFER_SCRATCH_FLAG_DEFAULT,
-    HB_BUFFER_MAX_LEN_DEFAULT,
-    HB_BUFFER_MAX_OPS_DEFAULT,
-
-    HB_BUFFER_CONTENT_TYPE_INVALID,
-    HB_SEGMENT_PROPERTIES_DEFAULT,
-    false, /* successful */
-    true, /* have_output */
-    true  /* have_positions */
-
-    /* Zero is good enough for everything else. */
-  };
-
-  return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
+  return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
 }
 
 /**
@@ -900,13 +873,12 @@
 hb_buffer_set_unicode_funcs (hb_buffer_t        *buffer,
                              hb_unicode_funcs_t *unicode_funcs)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   if (!unicode_funcs)
     unicode_funcs = hb_unicode_funcs_get_default ();
 
-
   hb_unicode_funcs_reference (unicode_funcs);
   hb_unicode_funcs_destroy (buffer->unicode);
   buffer->unicode = unicode_funcs;
@@ -948,7 +920,7 @@
                          hb_direction_t  direction)
 
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.direction = direction;
@@ -992,7 +964,7 @@
 hb_buffer_set_script (hb_buffer_t *buffer,
                       hb_script_t  script)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.script = script;
@@ -1027,7 +999,7 @@
  * are orthogonal to the scripts, and though they are related, they are
  * different concepts and should not be confused with each other.
  *
- * Use hb_language_from_string() to convert from ISO 639 language codes to
+ * Use hb_language_from_string() to convert from BCP 47 language tags to
  * #hb_language_t.
  *
  * Since: 0.9.2
@@ -1036,7 +1008,7 @@
 hb_buffer_set_language (hb_buffer_t   *buffer,
                         hb_language_t  language)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props.language = language;
@@ -1074,7 +1046,7 @@
 hb_buffer_set_segment_properties (hb_buffer_t *buffer,
                                   const hb_segment_properties_t *props)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->props = *props;
@@ -1110,7 +1082,7 @@
 hb_buffer_set_flags (hb_buffer_t       *buffer,
                      hb_buffer_flags_t  flags)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->flags = flags;
@@ -1146,7 +1118,7 @@
 hb_buffer_set_cluster_level (hb_buffer_t       *buffer,
                      hb_buffer_cluster_level_t  cluster_level)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->cluster_level = cluster_level;
@@ -1185,7 +1157,7 @@
 hb_buffer_set_replacement_codepoint (hb_buffer_t    *buffer,
                                      hb_codepoint_t  replacement)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   buffer->replacement = replacement;
@@ -1210,6 +1182,46 @@
 
 
 /**
+ * hb_buffer_set_invisible_glyph:
+ * @buffer: an #hb_buffer_t.
+ * @invisible: the invisible #hb_codepoint_t
+ *
+ * Sets the #hb_codepoint_t that replaces invisible characters in
+ * the shaping result.  If set to zero (default), the glyph for the
+ * U+0020 SPACE character is used.  Otherwise, this value is used
+ * verbatim.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_buffer_set_invisible_glyph (hb_buffer_t    *buffer,
+                               hb_codepoint_t  invisible)
+{
+  if (unlikely (hb_object_is_immutable (buffer)))
+    return;
+
+  buffer->invisible = invisible;
+}
+
+/**
+ * hb_buffer_get_invisible_glyph:
+ * @buffer: an #hb_buffer_t.
+ *
+ * See hb_buffer_set_invisible_glyph().
+ *
+ * Return value:
+ * The @buffer invisible #hb_codepoint_t.
+ *
+ * Since: 2.0.0
+ **/
+hb_codepoint_t
+hb_buffer_get_invisible_glyph (hb_buffer_t    *buffer)
+{
+  return buffer->invisible;
+}
+
+
+/**
  * hb_buffer_reset:
  * @buffer: an #hb_buffer_t.
  *
@@ -1317,7 +1329,7 @@
 hb_buffer_set_length (hb_buffer_t  *buffer,
                       unsigned int  length)
 {
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return length == 0;
 
   if (!buffer->ensure (length))
@@ -1498,6 +1510,8 @@
  * it will be set to the process's default language as returned by
  * hb_language_get_default().  This may change in the future by
  * taking buffer script into consideration when choosing a language.
+ * Note that hb_language_get_default() is NOT threadsafe the first time
+ * it is called.  See documentation for that function for details.
  *
  * Since: 0.9.7
  **/
@@ -1521,7 +1535,7 @@
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE ||
           (!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID));
 
-  if (unlikely (hb_object_is_inert (buffer)))
+  if (unlikely (hb_object_is_immutable (buffer)))
     return;
 
   if (text_length == -1)
@@ -1652,7 +1666,7 @@
                      unsigned int    item_offset,
                      int             item_length)
 {
-  hb_buffer_add_utf<hb_utf32_t<> > (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 /**
@@ -1713,7 +1727,7 @@
                           unsigned int          item_offset,
                           int                   item_length)
 {
-  hb_buffer_add_utf<hb_utf32_t<false> > (buffer, text, text_length, item_offset, item_length);
+  hb_buffer_add_utf<hb_utf32_novalidate_t> (buffer, text, text_length, item_offset, item_length);
 }
 
 
@@ -1886,6 +1900,10 @@
 
 /**
  * hb_buffer_diff:
+ * @buffer: a buffer.
+ * @reference: other buffer to compare to.
+ * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1.
+ * @position_fuzz: allowed absolute difference in position values.
  *
  * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
  * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned.  This should be used by most
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.h	Tue Mar 26 09:05:10 2019 -0400
@@ -44,7 +44,6 @@
  * hb_glyph_info_t:
  * @codepoint: either a Unicode code point (before shaping) or a glyph index
  *             (after shaping).
- * @mask:
  * @cluster: the index of the character in the original text that corresponds
  *           to this #hb_glyph_info_t, or whatever the client passes to
  *           hb_buffer_add(). More than one #hb_glyph_info_t can have the same
@@ -59,11 +58,13 @@
  *
  * The #hb_glyph_info_t is the structure that holds information about the
  * glyphs and their relation to input text.
- *
  */
-typedef struct hb_glyph_info_t {
+typedef struct hb_glyph_info_t
+{
   hb_codepoint_t codepoint;
-  hb_mask_t      mask; /* Holds hb_glyph_flags_t after hb_shape(), plus other things. */
+  /*< private >*/
+  hb_mask_t      mask;
+  /*< public >*/
   uint32_t       cluster;
 
   /*< private >*/
@@ -88,6 +89,9 @@
  *                                 of each line after line-breaking, or limiting
  *                                 the reshaping to a small piece around the
  *                                 breaking point only.
+ * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
+ *
+ * Since: 1.5.0
  */
 typedef enum { /*< flags >*/
   HB_GLYPH_FLAG_UNSAFE_TO_BREAK         = 0x00000001,
@@ -298,7 +302,15 @@
 HB_EXTERN hb_buffer_flags_t
 hb_buffer_get_flags (hb_buffer_t *buffer);
 
-/*
+/**
+ * hb_buffer_cluster_level_t:
+ * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES: Return cluster values grouped by graphemes into
+ *   monotone order.
+ * @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS: Return cluster values grouped into monotone order.
+ * @HB_BUFFER_CLUSTER_LEVEL_CHARACTERS: Don't group cluster values.
+ * @HB_BUFFER_CLUSTER_LEVEL_DEFAULT: Default cluster level,
+ *   equal to @HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES.
+ *
  * Since: 0.9.42
  */
 typedef enum {
@@ -332,6 +344,13 @@
 HB_EXTERN hb_codepoint_t
 hb_buffer_get_replacement_codepoint (hb_buffer_t    *buffer);
 
+HB_EXTERN void
+hb_buffer_set_invisible_glyph (hb_buffer_t    *buffer,
+                               hb_codepoint_t  invisible);
+
+HB_EXTERN hb_codepoint_t
+hb_buffer_get_invisible_glyph (hb_buffer_t    *buffer);
+
 
 HB_EXTERN void
 hb_buffer_reset (hb_buffer_t *buffer);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-buffer.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,439 @@
+/*
+ * Copyright © 1998-2004  David Turner and Werner Lemberg
+ * Copyright © 2004,2007,2009,2010  Red Hat, Inc.
+ * Copyright © 2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_BUFFER_HH
+#define HB_BUFFER_HH
+
+#include "hb.hh"
+#include "hb-unicode.hh"
+
+
+#ifndef HB_BUFFER_MAX_LEN_FACTOR
+#define HB_BUFFER_MAX_LEN_FACTOR 32
+#endif
+#ifndef HB_BUFFER_MAX_LEN_MIN
+#define HB_BUFFER_MAX_LEN_MIN 8192
+#endif
+#ifndef HB_BUFFER_MAX_LEN_DEFAULT
+#define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
+#endif
+
+#ifndef HB_BUFFER_MAX_OPS_FACTOR
+#define HB_BUFFER_MAX_OPS_FACTOR 64
+#endif
+#ifndef HB_BUFFER_MAX_OPS_MIN
+#define HB_BUFFER_MAX_OPS_MIN 1024
+#endif
+#ifndef HB_BUFFER_MAX_OPS_DEFAULT
+#define HB_BUFFER_MAX_OPS_DEFAULT 0x1FFFFFFF /* Shaping more than a billion operations? Let us know! */
+#endif
+
+static_assert ((sizeof (hb_glyph_info_t) == 20), "");
+static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
+
+HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
+HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
+HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
+
+enum hb_buffer_scratch_flags_t {
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT                        = 0x00000000u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII                  = 0x00000001u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES         = 0x00000002u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK             = 0x00000004u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT            = 0x00000008u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK            = 0x00000010u,
+  HB_BUFFER_SCRATCH_FLAG_HAS_CGJ                        = 0x00000020u,
+
+  /* Reserved for complex shapers' internal use. */
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX0                       = 0x01000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX1                       = 0x02000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX2                       = 0x04000000u,
+  HB_BUFFER_SCRATCH_FLAG_COMPLEX3                       = 0x08000000u,
+};
+HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
+
+
+/*
+ * hb_buffer_t
+ */
+
+struct hb_buffer_t
+{
+  hb_object_header_t header;
+
+  /* Information about how the text in the buffer should be treated */
+  hb_unicode_funcs_t *unicode; /* Unicode functions */
+  hb_buffer_flags_t flags; /* BOT / EOT / etc. */
+  hb_buffer_cluster_level_t cluster_level;
+  hb_codepoint_t replacement; /* U+FFFD or something else. */
+  hb_codepoint_t invisible; /* 0 or something else. */
+  hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
+  unsigned int max_len; /* Maximum allowed len. */
+  int max_ops; /* Maximum allowed operations. */
+
+  /* Buffer contents */
+  hb_buffer_content_type_t content_type;
+  hb_segment_properties_t props; /* Script, language, direction */
+
+  bool successful; /* Allocations successful */
+  bool have_output; /* Whether we have an output buffer going on */
+  bool have_positions; /* Whether we have positions */
+
+  unsigned int idx; /* Cursor into ->info and ->pos arrays */
+  unsigned int len; /* Length of ->info and ->pos arrays */
+  unsigned int out_len; /* Length of ->out array if have_output */
+
+  unsigned int allocated; /* Length of allocated arrays */
+  hb_glyph_info_t     *info;
+  hb_glyph_info_t     *out_info;
+  hb_glyph_position_t *pos;
+
+  unsigned int serial;
+
+  /* Text before / after the main buffer contents.
+   * Always in Unicode, and ordered outward.
+   * Index 0 is for "pre-context", 1 for "post-context". */
+  static constexpr unsigned CONTEXT_LENGTH = 5u;
+  hb_codepoint_t context[2][CONTEXT_LENGTH];
+  unsigned int context_len[2];
+
+  /* Debugging API */
+  hb_buffer_message_func_t message_func;
+  void *message_data;
+  hb_destroy_func_t message_destroy;
+
+  /* Internal debugging. */
+  /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
+#ifndef HB_NDEBUG
+  uint8_t allocated_var_bits;
+#endif
+
+
+  /* Methods */
+
+  bool in_error () const { return !successful; }
+
+  void allocate_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (0 == (allocated_var_bits & bits));
+    allocated_var_bits |= bits;
+#endif
+  }
+  void deallocate_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (bits == (allocated_var_bits & bits));
+    allocated_var_bits &= ~bits;
+#endif
+  }
+  void assert_var (unsigned int start, unsigned int count)
+  {
+#ifndef HB_NDEBUG
+    unsigned int end = start + count;
+    assert (end <= 8);
+    unsigned int bits = (1u<<end) - (1u<<start);
+    assert (bits == (allocated_var_bits & bits));
+#endif
+  }
+  void deallocate_var_all ()
+  {
+#ifndef HB_NDEBUG
+    allocated_var_bits = 0;
+#endif
+  }
+
+  hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
+  hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
+
+  hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
+  hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
+
+  hb_glyph_info_t &prev ()      { return out_info[out_len ? out_len - 1 : 0]; }
+  hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; }
+
+  bool has_separate_output () const { return info != out_info; }
+
+
+  HB_INTERNAL void reset ();
+  HB_INTERNAL void clear ();
+
+  unsigned int backtrack_len () const { return have_output? out_len : idx; }
+  unsigned int lookahead_len () const { return len - idx; }
+  unsigned int next_serial () { return serial++; }
+
+  HB_INTERNAL void add (hb_codepoint_t  codepoint,
+                        unsigned int    cluster);
+  HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
+
+  HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
+  HB_INTERNAL void reverse ();
+  HB_INTERNAL void reverse_clusters ();
+  HB_INTERNAL void guess_segment_properties ();
+
+  HB_INTERNAL void swap_buffers ();
+  HB_INTERNAL void remove_output ();
+  HB_INTERNAL void clear_output ();
+  HB_INTERNAL void clear_positions ();
+
+  HB_INTERNAL void replace_glyphs (unsigned int num_in,
+                                   unsigned int num_out,
+                                   const hb_codepoint_t *glyph_data);
+
+  void replace_glyph (hb_codepoint_t glyph_index)
+  {
+    if (unlikely (out_info != info || out_len != idx)) {
+      if (unlikely (!make_room_for (1, 1))) return;
+      out_info[out_len] = info[idx];
+    }
+    out_info[out_len].codepoint = glyph_index;
+
+    idx++;
+    out_len++;
+  }
+  /* Makes a copy of the glyph at idx to output and replace glyph_index */
+  hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index)
+  {
+    if (unlikely (!make_room_for (0, 1))) return Crap(hb_glyph_info_t);
+
+    if (unlikely (idx == len && !out_len))
+      return Crap(hb_glyph_info_t);
+
+    out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1];
+    out_info[out_len].codepoint = glyph_index;
+
+    out_len++;
+
+    return out_info[out_len - 1];
+  }
+  void output_info (const hb_glyph_info_t &glyph_info)
+  {
+    if (unlikely (!make_room_for (0, 1))) return;
+
+    out_info[out_len] = glyph_info;
+
+    out_len++;
+  }
+  /* Copies glyph at idx to output but doesn't advance idx */
+  void copy_glyph ()
+  {
+    if (unlikely (!make_room_for (0, 1))) return;
+
+    out_info[out_len] = info[idx];
+
+    out_len++;
+  }
+  /* Copies glyph at idx to output and advance idx.
+   * If there's no output, just advance idx. */
+  void
+  next_glyph ()
+  {
+    if (have_output)
+    {
+      if (out_info != info || out_len != idx)
+      {
+        if (unlikely (!make_room_for (1, 1))) return;
+        out_info[out_len] = info[idx];
+      }
+      out_len++;
+    }
+
+    idx++;
+  }
+  /* Copies n glyphs at idx to output and advance idx.
+   * If there's no output, just advance idx. */
+  void
+  next_glyphs (unsigned int n)
+  {
+    if (have_output)
+    {
+      if (out_info != info || out_len != idx)
+      {
+        if (unlikely (!make_room_for (n, n))) return;
+        memmove (out_info + out_len, info + idx, n * sizeof (out_info[0]));
+      }
+      out_len += n;
+    }
+
+    idx += n;
+  }
+  /* Advance idx without copying to output. */
+  void skip_glyph () { idx++; }
+  void reset_masks (hb_mask_t mask)
+  {
+    for (unsigned int j = 0; j < len; j++)
+      info[j].mask = mask;
+  }
+  void add_masks (hb_mask_t mask)
+  {
+    for (unsigned int j = 0; j < len; j++)
+      info[j].mask |= mask;
+  }
+  HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask,
+                              unsigned int cluster_start, unsigned int cluster_end);
+
+  void merge_clusters (unsigned int start, unsigned int end)
+  {
+    if (end - start < 2)
+      return;
+    merge_clusters_impl (start, end);
+  }
+  HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end);
+  HB_INTERNAL void merge_out_clusters (unsigned int start, unsigned int end);
+  /* Merge clusters for deleting current glyph, and skip it. */
+  HB_INTERNAL void delete_glyph ();
+
+  void unsafe_to_break (unsigned int start,
+                               unsigned int end)
+  {
+    if (end - start < 2)
+      return;
+    unsafe_to_break_impl (start, end);
+  }
+  HB_INTERNAL void unsafe_to_break_impl (unsigned int start, unsigned int end);
+  HB_INTERNAL void unsafe_to_break_from_outbuffer (unsigned int start, unsigned int end);
+
+
+  /* Internal methods */
+  HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
+
+  HB_INTERNAL bool enlarge (unsigned int size);
+
+  bool ensure (unsigned int size)
+  { return likely (!size || size < allocated) ? true : enlarge (size); }
+
+  bool ensure_inplace (unsigned int size)
+  { return likely (!size || size < allocated); }
+
+  HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
+  HB_INTERNAL bool shift_forward (unsigned int count);
+
+  typedef long scratch_buffer_t;
+  HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
+
+  void clear_context (unsigned int side) { context_len[side] = 0; }
+
+  HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
+
+  bool messaging () { return unlikely (message_func); }
+  bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
+  {
+    if (!messaging ())
+      return true;
+    va_list ap;
+    va_start (ap, fmt);
+    bool ret = message_impl (font, fmt, ap);
+    va_end (ap);
+    return ret;
+  }
+  HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
+
+  static void
+  set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
+  {
+    if (inf.cluster != cluster)
+    {
+      if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
+        inf.mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+      else
+        inf.mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+    }
+    inf.cluster = cluster;
+  }
+
+  int
+  _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
+                                     unsigned int start, unsigned int end,
+                                     unsigned int cluster) const
+  {
+    for (unsigned int i = start; i < end; i++)
+      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
+    return cluster;
+  }
+  void
+  _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
+                             unsigned int start, unsigned int end,
+                             unsigned int cluster)
+  {
+    for (unsigned int i = start; i < end; i++)
+      if (cluster != infos[i].cluster)
+      {
+        scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK;
+        infos[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+      }
+  }
+
+  void unsafe_to_break_all ()
+  { unsafe_to_break_impl (0, len); }
+  void safe_to_break_all ()
+  {
+    for (unsigned int i = 0; i < len; i++)
+      info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+  }
+};
+DECLARE_NULL_INSTANCE (hb_buffer_t);
+
+
+/* Loop over clusters. Duplicated in foreach_syllable(). */
+#define foreach_cluster(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _next_cluster (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _next_cluster (buffer, start))
+
+static inline unsigned int
+_next_cluster (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  unsigned int cluster = info[start].cluster;
+  while (++start < count && cluster == info[start].cluster)
+    ;
+
+  return start;
+}
+
+
+#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
+  b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
+           sizeof (b->info[0].var))
+#define HB_BUFFER_ALLOCATE_VAR(b, var)          HB_BUFFER_XALLOCATE_VAR (b, allocate_var,   var ())
+#define HB_BUFFER_DEALLOCATE_VAR(b, var)        HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
+#define HB_BUFFER_ASSERT_VAR(b, var)            HB_BUFFER_XALLOCATE_VAR (b, assert_var,     var ())
+
+
+#endif /* HB_BUFFER_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-common.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,725 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF_INTERP_COMMON_HH
+#define HB_CFF_INTERP_COMMON_HH
+
+namespace CFF {
+
+using namespace OT;
+
+typedef unsigned int op_code_t;
+
+
+/* === Dict operators === */
+
+/* One byte operators (0-31) */
+#define OpCode_version            0 /* CFF Top */
+#define OpCode_Notice             1 /* CFF Top */
+#define OpCode_FullName           2 /* CFF Top */
+#define OpCode_FamilyName         3 /* CFF Top */
+#define OpCode_Weight             4 /* CFF Top */
+#define OpCode_FontBBox           5 /* CFF Top */
+#define OpCode_BlueValues         6 /* CFF Private, CFF2 Private */
+#define OpCode_OtherBlues         7 /* CFF Private, CFF2 Private */
+#define OpCode_FamilyBlues        8 /* CFF Private, CFF2 Private */
+#define OpCode_FamilyOtherBlues   9 /* CFF Private, CFF2 Private */
+#define OpCode_StdHW             10 /* CFF Private, CFF2 Private */
+#define OpCode_StdVW             11 /* CFF Private, CFF2 Private */
+#define OpCode_escape            12 /* All. Shared with CS */
+#define OpCode_UniqueID          13 /* CFF Top */
+#define OpCode_XUID              14 /* CFF Top */
+#define OpCode_charset           15 /* CFF Top (0) */
+#define OpCode_Encoding          16 /* CFF Top (0) */
+#define OpCode_CharStrings       17 /* CFF Top, CFF2 Top */
+#define OpCode_Private           18 /* CFF Top, CFF2 FD */
+#define OpCode_Subrs             19 /* CFF Private, CFF2 Private */
+#define OpCode_defaultWidthX     20 /* CFF Private (0) */
+#define OpCode_nominalWidthX     21 /* CFF Private (0) */
+#define OpCode_vsindexdict       22 /* CFF2 Private/CS */
+#define OpCode_blenddict         23 /* CFF2 Private/CS */
+#define OpCode_vstore            24 /* CFF2 Top */
+#define OpCode_reserved25        25
+#define OpCode_reserved26        26
+#define OpCode_reserved27        27
+
+/* Numbers */
+#define OpCode_shortint          28 /* 16-bit integer, All */
+#define OpCode_longintdict       29 /* 32-bit integer, All */
+#define OpCode_BCD               30 /* Real number, CFF2 Top/FD */
+#define OpCode_reserved31        31
+
+/* 1-byte integers */
+#define OpCode_OneByteIntFirst   32 /* All. beginning of the range of first byte ints */
+#define OpCode_OneByteIntLast   246 /* All. ending of the range of first byte int */
+
+/* 2-byte integers */
+#define OpCode_TwoBytePosInt0   247 /* All. first byte of two byte positive int (+108 to +1131) */
+#define OpCode_TwoBytePosInt1   248
+#define OpCode_TwoBytePosInt2   249
+#define OpCode_TwoBytePosInt3   250
+
+#define OpCode_TwoByteNegInt0   251 /* All. first byte of two byte negative int (-1131 to -108) */
+#define OpCode_TwoByteNegInt1   252
+#define OpCode_TwoByteNegInt2   253
+#define OpCode_TwoByteNegInt3   254
+
+/* Two byte escape operators 12, (0-41) */
+#define OpCode_ESC_Base         256
+#define Make_OpCode_ESC(byte2)  ((op_code_t)(OpCode_ESC_Base + (byte2)))
+
+inline op_code_t Unmake_OpCode_ESC (op_code_t op)  { return (op_code_t)(op - OpCode_ESC_Base); }
+inline bool Is_OpCode_ESC (op_code_t op) { return op >= OpCode_ESC_Base; }
+inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2: 1; }
+
+#define OpCode_Copyright        Make_OpCode_ESC(0) /* CFF Top */
+#define OpCode_isFixedPitch     Make_OpCode_ESC(1) /* CFF Top (false) */
+#define OpCode_ItalicAngle      Make_OpCode_ESC(2) /* CFF Top (0) */
+#define OpCode_UnderlinePosition Make_OpCode_ESC(3) /* CFF Top (-100) */
+#define OpCode_UnderlineThickness Make_OpCode_ESC(4) /* CFF Top (50) */
+#define OpCode_PaintType        Make_OpCode_ESC(5) /* CFF Top (0) */
+#define OpCode_CharstringType   Make_OpCode_ESC(6) /* CFF Top (2) */
+#define OpCode_FontMatrix       Make_OpCode_ESC(7) /* CFF Top, CFF2 Top (.001 0 0 .001 0 0)*/
+#define OpCode_StrokeWidth      Make_OpCode_ESC(8) /* CFF Top (0) */
+#define OpCode_BlueScale        Make_OpCode_ESC(9) /* CFF Private, CFF2 Private (0.039625) */
+#define OpCode_BlueShift        Make_OpCode_ESC(10) /* CFF Private, CFF2 Private (7) */
+#define OpCode_BlueFuzz         Make_OpCode_ESC(11) /* CFF Private, CFF2 Private (1) */
+#define OpCode_StemSnapH        Make_OpCode_ESC(12) /* CFF Private, CFF2 Private */
+#define OpCode_StemSnapV        Make_OpCode_ESC(13) /* CFF Private, CFF2 Private */
+#define OpCode_ForceBold        Make_OpCode_ESC(14) /* CFF Private (false) */
+#define OpCode_reservedESC15    Make_OpCode_ESC(15)
+#define OpCode_reservedESC16    Make_OpCode_ESC(16)
+#define OpCode_LanguageGroup    Make_OpCode_ESC(17) /* CFF Private, CFF2 Private (0) */
+#define OpCode_ExpansionFactor  Make_OpCode_ESC(18) /* CFF Private, CFF2 Private (0.06) */
+#define OpCode_initialRandomSeed Make_OpCode_ESC(19) /* CFF Private (0) */
+#define OpCode_SyntheticBase    Make_OpCode_ESC(20) /* CFF Top */
+#define OpCode_PostScript       Make_OpCode_ESC(21) /* CFF Top */
+#define OpCode_BaseFontName     Make_OpCode_ESC(22) /* CFF Top */
+#define OpCode_BaseFontBlend    Make_OpCode_ESC(23) /* CFF Top */
+#define OpCode_reservedESC24    Make_OpCode_ESC(24)
+#define OpCode_reservedESC25    Make_OpCode_ESC(25)
+#define OpCode_reservedESC26    Make_OpCode_ESC(26)
+#define OpCode_reservedESC27    Make_OpCode_ESC(27)
+#define OpCode_reservedESC28    Make_OpCode_ESC(28)
+#define OpCode_reservedESC29    Make_OpCode_ESC(29)
+#define OpCode_ROS              Make_OpCode_ESC(30) /* CFF Top_CID */
+#define OpCode_CIDFontVersion   Make_OpCode_ESC(31) /* CFF Top_CID (0) */
+#define OpCode_CIDFontRevision  Make_OpCode_ESC(32) /* CFF Top_CID (0) */
+#define OpCode_CIDFontType      Make_OpCode_ESC(33) /* CFF Top_CID (0) */
+#define OpCode_CIDCount         Make_OpCode_ESC(34) /* CFF Top_CID (8720) */
+#define OpCode_UIDBase          Make_OpCode_ESC(35) /* CFF Top_CID */
+#define OpCode_FDArray          Make_OpCode_ESC(36) /* CFF Top_CID, CFF2 Top */
+#define OpCode_FDSelect         Make_OpCode_ESC(37) /* CFF Top_CID, CFF2 Top */
+#define OpCode_FontName         Make_OpCode_ESC(38) /* CFF Top_CID */
+
+
+/* === CharString operators === */
+
+#define OpCode_hstem              1 /* CFF, CFF2 */
+#define OpCode_Reserved2          2
+#define OpCode_vstem              3 /* CFF, CFF2 */
+#define OpCode_vmoveto            4 /* CFF, CFF2 */
+#define OpCode_rlineto            5 /* CFF, CFF2 */
+#define OpCode_hlineto            6 /* CFF, CFF2 */
+#define OpCode_vlineto            7 /* CFF, CFF2 */
+#define OpCode_rrcurveto          8 /* CFF, CFF2 */
+#define OpCode_Reserved9          9
+#define OpCode_callsubr          10 /* CFF, CFF2 */
+#define OpCode_return            11 /* CFF */
+//#define OpCode_escape          12 /* CFF, CFF2 */
+#define OpCode_Reserved13        13
+#define OpCode_endchar           14 /* CFF */
+#define OpCode_vsindexcs         15 /* CFF2 */
+#define OpCode_blendcs           16 /* CFF2 */
+#define OpCode_Reserved17        17
+#define OpCode_hstemhm           18 /* CFF, CFF2 */
+#define OpCode_hintmask          19 /* CFF, CFF2 */
+#define OpCode_cntrmask          20 /* CFF, CFF2 */
+#define OpCode_rmoveto           21 /* CFF, CFF2 */
+#define OpCode_hmoveto           22 /* CFF, CFF2 */
+#define OpCode_vstemhm           23 /* CFF, CFF2 */
+#define OpCode_rcurveline        24 /* CFF, CFF2 */
+#define OpCode_rlinecurve        25 /* CFF, CFF2 */
+#define OpCode_vvcurveto         26 /* CFF, CFF2 */
+#define OpCode_hhcurveto         27 /* CFF, CFF2 */
+//#define OpCode_shortint        28 /* CFF, CFF2 */
+#define OpCode_callgsubr         29 /* CFF, CFF2 */
+#define OpCode_vhcurveto         30 /* CFF, CFF2 */
+#define OpCode_hvcurveto         31 /* CFF, CFF2 */
+
+#define OpCode_fixedcs          255 /* 32-bit fixed */
+
+/* Two byte escape operators 12, (0-41) */
+#define OpCode_dotsection       Make_OpCode_ESC(0) /* CFF (obsoleted) */
+#define OpCode_ReservedESC1     Make_OpCode_ESC(1)
+#define OpCode_ReservedESC2     Make_OpCode_ESC(2)
+#define OpCode_and              Make_OpCode_ESC(3) /* CFF */
+#define OpCode_or               Make_OpCode_ESC(4) /* CFF */
+#define OpCode_not              Make_OpCode_ESC(5) /* CFF */
+#define OpCode_ReservedESC6     Make_OpCode_ESC(6)
+#define OpCode_ReservedESC7     Make_OpCode_ESC(7)
+#define OpCode_ReservedESC8     Make_OpCode_ESC(8)
+#define OpCode_abs              Make_OpCode_ESC(9) /* CFF */
+#define OpCode_add              Make_OpCode_ESC(10) /* CFF */
+#define OpCode_sub              Make_OpCode_ESC(11) /* CFF */
+#define OpCode_div              Make_OpCode_ESC(12) /* CFF */
+#define OpCode_ReservedESC13    Make_OpCode_ESC(13)
+#define OpCode_neg              Make_OpCode_ESC(14) /* CFF */
+#define OpCode_eq               Make_OpCode_ESC(15) /* CFF */
+#define OpCode_ReservedESC16    Make_OpCode_ESC(16)
+#define OpCode_ReservedESC17    Make_OpCode_ESC(17)
+#define OpCode_drop             Make_OpCode_ESC(18) /* CFF */
+#define OpCode_ReservedESC19    Make_OpCode_ESC(19)
+#define OpCode_put              Make_OpCode_ESC(20) /* CFF */
+#define OpCode_get              Make_OpCode_ESC(21) /* CFF */
+#define OpCode_ifelse           Make_OpCode_ESC(22) /* CFF */
+#define OpCode_random           Make_OpCode_ESC(23) /* CFF */
+#define OpCode_mul              Make_OpCode_ESC(24) /* CFF */
+//#define OpCode_reservedESC25  Make_OpCode_ESC(25)
+#define OpCode_sqrt             Make_OpCode_ESC(26) /* CFF */
+#define OpCode_dup              Make_OpCode_ESC(27) /* CFF */
+#define OpCode_exch             Make_OpCode_ESC(28) /* CFF */
+#define OpCode_index            Make_OpCode_ESC(29) /* CFF */
+#define OpCode_roll             Make_OpCode_ESC(30) /* CFF */
+#define OpCode_reservedESC31    Make_OpCode_ESC(31)
+#define OpCode_reservedESC32    Make_OpCode_ESC(32)
+#define OpCode_reservedESC33    Make_OpCode_ESC(33)
+#define OpCode_hflex            Make_OpCode_ESC(34) /* CFF, CFF2 */
+#define OpCode_flex             Make_OpCode_ESC(35) /* CFF, CFF2 */
+#define OpCode_hflex1           Make_OpCode_ESC(36) /* CFF, CFF2 */
+#define OpCode_flex1            Make_OpCode_ESC(37) /* CFF, CFF2 */
+
+
+#define OpCode_Invalid          0xFFFFu
+
+
+struct number_t
+{
+  void init () { set_real (0.0); }
+  void fini () {}
+
+  void set_int (int v)       { value = (double) v; }
+  int to_int () const        { return (int) value; }
+
+  void set_fixed (int32_t v) { value = v / 65536.0; }
+  int32_t to_fixed () const  { return (int32_t) (value * 65536.0); }
+
+  void set_real (double v)       { value = v; }
+  double to_real () const    { return value; }
+
+  int ceil () const          { return (int) ::ceil (value); }
+  int floor () const         { return (int) ::floor (value); }
+
+  bool in_int_range () const
+  { return ((double) (int16_t) to_int () == value); }
+
+  bool operator > (const number_t &n) const
+  { return value > n.to_real (); }
+
+  bool operator < (const number_t &n) const
+  { return n > *this; }
+
+  bool operator >= (const number_t &n) const
+  { return !(*this < n); }
+
+  bool operator <= (const number_t &n) const
+  { return !(*this > n); }
+
+  const number_t &operator += (const number_t &n)
+  {
+    set_real (to_real () + n.to_real ());
+
+    return *this;
+  }
+
+  protected:
+  double  value;
+};
+
+/* byte string */
+struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
+{
+  // encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
+  template <typename INTTYPE, int minVal, int maxVal>
+  static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, int value)
+  {
+    TRACE_SERIALIZE (this);
+
+    if (unlikely ((value < minVal || value > maxVal)))
+      return_trace (false);
+
+    HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+    if (unlikely (p == nullptr)) return_trace (false);
+    p->set (intOp);
+
+    INTTYPE *ip = c->allocate_size<INTTYPE> (INTTYPE::static_size);
+    if (unlikely (ip == nullptr)) return_trace (false);
+    ip->set ((unsigned int)value);
+
+    return_trace (true);
+  }
+
+  static bool serialize_int4 (hb_serialize_context_t *c, int value)
+  { return serialize_int<HBUINT32, 0, 0x7FFFFFFF> (c, OpCode_longintdict, value); }
+
+  static bool serialize_int2 (hb_serialize_context_t *c, int value)
+  { return serialize_int<HBUINT16, 0, 0x7FFF> (c, OpCode_shortint, value); }
+
+  /* Defining null_size allows a Null object may be created. Should be safe because:
+   * A descendent struct Dict uses a Null pointer to indicate a missing table,
+   * checked before access.
+   * byte_str_t, a wrapper struct pairing a byte pointer along with its length, always
+   * checks the length before access. A Null pointer is used as the initial pointer
+   * along with zero length by the default ctor.
+   */
+  DEFINE_SIZE_MIN(0);
+};
+
+/* Holder of a section of byte string within a CFFIndex entry */
+struct byte_str_t : hb_ubytes_t
+{
+  byte_str_t ()
+    : hb_ubytes_t () {}
+  byte_str_t (const UnsizedByteStr& s, unsigned int l)
+    : hb_ubytes_t ((const unsigned char*)&s, l) {}
+  byte_str_t (const unsigned char *s, unsigned int l)
+    : hb_ubytes_t (s, l) {}
+  byte_str_t (const hb_ubytes_t &ub)    /* conversion from hb_ubytes_t */
+    : hb_ubytes_t (ub) {}
+
+  /* sub-string */
+  byte_str_t sub_str (unsigned int offset, unsigned int len_) const
+  { return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); }
+
+  bool check_limit (unsigned int offset, unsigned int count) const
+  { return (offset + count <= length); }
+};
+
+/* A byte string associated with the current offset and an error condition */
+struct byte_str_ref_t
+{
+  byte_str_ref_t ()
+  { init (); }
+
+  void init ()
+  {
+    str = byte_str_t ();
+    offset = 0;
+    error = false;
+  }
+
+  void fini () {}
+
+  byte_str_ref_t (const byte_str_t &str_, unsigned int offset_ = 0)
+    : str (str_), offset (offset_), error (false) {}
+
+  void reset (const byte_str_t &str_, unsigned int offset_ = 0)
+  {
+    str = str_;
+    offset = offset_;
+    error = false;
+  }
+
+  const unsigned char& operator [] (int i) {
+    if (unlikely ((unsigned int)(offset + i) >= str.length))
+    {
+      set_error ();
+      return Null(unsigned char);
+    }
+    else
+      return str[offset + i];
+  }
+
+  /* Conversion to byte_str_t */
+  operator byte_str_t () const { return str.sub_str (offset, str.length - offset); }
+
+  byte_str_t sub_str (unsigned int offset_, unsigned int len_) const
+  { return str.sub_str (offset_, len_); }
+
+  bool avail (unsigned int count=1) const
+  {
+    return (!in_error () && str.check_limit (offset, count));
+  }
+  void inc (unsigned int count=1)
+  {
+    if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
+    {
+      offset += count;
+    }
+    else
+    {
+      offset = str.length;
+      set_error ();
+    }
+  }
+
+  void set_error ()      { error = true; }
+  bool in_error () const { return error; }
+
+  byte_str_t       str;
+  unsigned int  offset; /* beginning of the sub-string within str */
+
+  protected:
+  bool    error;
+};
+
+typedef hb_vector_t<byte_str_t> byte_str_array_t;
+
+/* stack */
+template <typename ELEM, int LIMIT>
+struct stack_t
+{
+  void init ()
+  {
+    error = false;
+    count = 0;
+    elements.init ();
+    elements.resize (kSizeLimit);
+    for (unsigned int i = 0; i < elements.length; i++)
+      elements[i].init ();
+  }
+
+  void fini ()
+  {
+    elements.fini_deep ();
+  }
+
+  ELEM& operator [] (unsigned int i)
+  {
+    if (unlikely (i >= count)) set_error ();
+    return elements[i];
+  }
+
+  void push (const ELEM &v)
+  {
+    if (likely (count < elements.length))
+      elements[count++] = v;
+    else
+      set_error ();
+  }
+
+  ELEM &push ()
+  {
+    if (likely (count < elements.length))
+      return elements[count++];
+    else
+    {
+      set_error ();
+      return Crap(ELEM);
+    }
+  }
+
+  ELEM& pop ()
+  {
+    if (likely (count > 0))
+      return elements[--count];
+    else
+    {
+      set_error ();
+      return Crap(ELEM);
+    }
+  }
+
+  void pop (unsigned int n)
+  {
+    if (likely (count >= n))
+      count -= n;
+    else
+      set_error ();
+  }
+
+  const ELEM& peek ()
+  {
+    if (likely (count > 0))
+      return elements[count-1];
+    else
+    {
+      set_error ();
+      return Null(ELEM);
+    }
+  }
+
+  void unpop ()
+  {
+    if (likely (count < elements.length))
+      count++;
+    else
+      set_error ();
+  }
+
+  void clear () { count = 0; }
+
+  bool in_error () const { return (error || elements.in_error ()); }
+  void set_error ()      { error = true; }
+
+  unsigned int get_count () const { return count; }
+  bool is_empty () const { return count == 0; }
+
+  static constexpr unsigned kSizeLimit = LIMIT;
+
+  protected:
+  bool error;
+  unsigned int count;
+  hb_vector_t<ELEM> elements;
+};
+
+/* argument stack */
+template <typename ARG=number_t>
+struct arg_stack_t : stack_t<ARG, 513>
+{
+  void push_int (int v)
+  {
+    ARG &n = S::push ();
+    n.set_int (v);
+  }
+
+  void push_fixed (int32_t v)
+  {
+    ARG &n = S::push ();
+    n.set_fixed (v);
+  }
+
+  void push_real (double v)
+  {
+    ARG &n = S::push ();
+    n.set_real (v);
+  }
+
+  ARG& pop_num () { return this->pop (); }
+
+  int pop_int ()  { return this->pop ().to_int (); }
+
+  unsigned int pop_uint ()
+  {
+    int i = pop_int ();
+    if (unlikely (i < 0))
+    {
+      i = 0;
+      S::set_error ();
+    }
+    return (unsigned)i;
+  }
+
+  void push_longint_from_substr (byte_str_ref_t& str_ref)
+  {
+    push_int ((str_ref[0] << 24) | (str_ref[1] << 16) | (str_ref[2] << 8) | (str_ref[3]));
+    str_ref.inc (4);
+  }
+
+  bool push_fixed_from_substr (byte_str_ref_t& str_ref)
+  {
+    if (unlikely (!str_ref.avail (4)))
+      return false;
+    push_fixed ((int32_t)*(const HBUINT32*)&str_ref[0]);
+    str_ref.inc (4);
+    return true;
+  }
+
+  hb_array_t<const ARG> get_subarray (unsigned int start) const
+  {
+    return S::elements.sub_array (start);
+  }
+
+  private:
+  typedef stack_t<ARG, 513> S;
+};
+
+/* an operator prefixed by its operands in a byte string */
+struct op_str_t
+{
+  void init () {}
+  void fini () {}
+
+  op_code_t  op;
+  byte_str_t str;
+};
+
+/* base of OP_SERIALIZER */
+struct op_serializer_t
+{
+  protected:
+  bool copy_opstr (hb_serialize_context_t *c, const op_str_t& opstr) const
+  {
+    TRACE_SERIALIZE (this);
+
+    HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+    if (unlikely (d == nullptr)) return_trace (false);
+    memcpy (d, &opstr.str[0], opstr.str.length);
+    return_trace (true);
+  }
+};
+
+template <typename VAL>
+struct parsed_values_t
+{
+  void init ()
+  {
+    opStart = 0;
+    values.init ();
+  }
+  void fini () { values.fini_deep (); }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
+  {
+    VAL *val = values.push ();
+    val->op = op;
+    val->str = str_ref.str.sub_str (opStart, str_ref.offset - opStart);
+    opStart = str_ref.offset;
+  }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v)
+  {
+    VAL *val = values.push (v);
+    val->op = op;
+    val->str = str_ref.sub_str ( opStart, str_ref.offset - opStart);
+    opStart = str_ref.offset;
+  }
+
+  bool has_op (op_code_t op) const
+  {
+    for (unsigned int i = 0; i < get_count (); i++)
+      if (get_value (i).op == op) return true;
+    return false;
+  }
+
+  unsigned get_count () const { return values.length; }
+  const VAL &get_value (unsigned int i) const { return values[i]; }
+  const VAL &operator [] (unsigned int i) const { return get_value (i); }
+
+  unsigned int       opStart;
+  hb_vector_t<VAL>   values;
+};
+
+template <typename ARG=number_t>
+struct interp_env_t
+{
+  void init (const byte_str_t &str_)
+  {
+    str_ref.reset (str_);
+    argStack.init ();
+    error = false;
+  }
+  void fini () { argStack.fini (); }
+
+  bool in_error () const
+  { return error || str_ref.in_error () || argStack.in_error (); }
+
+  void set_error () { error = true; }
+
+  op_code_t fetch_op ()
+  {
+    op_code_t  op = OpCode_Invalid;
+    if (unlikely (!str_ref.avail ()))
+      return OpCode_Invalid;
+    op = (op_code_t)(unsigned char)str_ref[0];
+    if (op == OpCode_escape) {
+      if (unlikely (!str_ref.avail ()))
+        return OpCode_Invalid;
+      op = Make_OpCode_ESC(str_ref[1]);
+      str_ref.inc ();
+    }
+    str_ref.inc ();
+    return op;
+  }
+
+  const ARG& eval_arg (unsigned int i)
+  {
+    return argStack[i];
+  }
+
+  ARG& pop_arg ()
+  {
+    return argStack.pop ();
+  }
+
+  void pop_n_args (unsigned int n)
+  {
+    argStack.pop (n);
+  }
+
+  void clear_args ()
+  {
+    pop_n_args (argStack.get_count ());
+  }
+
+  byte_str_ref_t    str_ref;
+  arg_stack_t<ARG> argStack;
+  protected:
+  bool    error;
+};
+
+typedef interp_env_t<> num_interp_env_t;
+
+template <typename ARG=number_t>
+struct opset_t
+{
+  static void process_op (op_code_t op, interp_env_t<ARG>& env)
+  {
+    switch (op) {
+      case OpCode_shortint:
+        env.argStack.push_int ((int16_t)((env.str_ref[0] << 8) | env.str_ref[1]));
+        env.str_ref.inc (2);
+        break;
+
+      case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
+      case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
+        env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.str_ref[0] + 108));
+        env.str_ref.inc ();
+        break;
+
+      case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
+      case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
+        env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
+        env.str_ref.inc ();
+        break;
+
+      default:
+        /* 1-byte integer */
+        if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)))
+        {
+          env.argStack.push_int ((int)op - 139);
+        } else {
+          /* invalid unknown operator */
+          env.clear_args ();
+          env.set_error ();
+        }
+        break;
+    }
+  }
+};
+
+template <typename ENV>
+struct interpreter_t {
+
+  ~interpreter_t() { fini (); }
+
+  void fini () { env.fini (); }
+
+  ENV env;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-cs-common.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,905 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF_INTERP_CS_COMMON_HH
+#define HB_CFF_INTERP_CS_COMMON_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+enum cs_type_t {
+  CSType_CharString,
+  CSType_GlobalSubr,
+  CSType_LocalSubr
+};
+
+struct call_context_t
+{
+  void init (const byte_str_ref_t substr_=byte_str_ref_t (), cs_type_t type_=CSType_CharString, unsigned int subr_num_=0)
+  {
+    str_ref = substr_;
+    type = type_;
+    subr_num = subr_num_;
+  }
+
+  void fini () {}
+
+  byte_str_ref_t  str_ref;
+  cs_type_t       type;
+  unsigned int    subr_num;
+};
+
+/* call stack */
+const unsigned int kMaxCallLimit = 10;
+struct call_stack_t : stack_t<call_context_t, kMaxCallLimit> {};
+
+template <typename SUBRS>
+struct biased_subrs_t
+{
+  void init (const SUBRS &subrs_)
+  {
+    subrs = &subrs_;
+    unsigned int  nSubrs = get_count ();
+    if (nSubrs < 1240)
+      bias = 107;
+    else if (nSubrs < 33900)
+      bias = 1131;
+    else
+      bias = 32768;
+  }
+
+  void fini () {}
+
+  unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; }
+  unsigned int get_bias () const { return bias; }
+
+  byte_str_t operator [] (unsigned int index) const
+  {
+    if (unlikely ((subrs == nullptr) || index >= subrs->count))
+      return Null(byte_str_t);
+    else
+      return (*subrs)[index];
+  }
+
+  protected:
+  unsigned int  bias;
+  const SUBRS   *subrs;
+};
+
+struct point_t
+{
+  void init ()
+  {
+    x.init ();
+    y.init ();
+  }
+
+  void set_int (int _x, int _y)
+  {
+    x.set_int (_x);
+    y.set_int (_y);
+  }
+
+  void move_x (const number_t &dx) { x += dx; }
+  void move_y (const number_t &dy) { y += dy; }
+  void move (const number_t &dx, const number_t &dy) { move_x (dx); move_y (dy); }
+  void move (const point_t &d) { move_x (d.x); move_y (d.y); }
+
+  number_t  x;
+  number_t  y;
+};
+
+template <typename ARG, typename SUBRS>
+struct cs_interp_env_t : interp_env_t<ARG>
+{
+  void init (const byte_str_t &str, const SUBRS &globalSubrs_, const SUBRS &localSubrs_)
+  {
+    interp_env_t<ARG>::init (str);
+
+    context.init (str, CSType_CharString);
+    seen_moveto = true;
+    seen_hintmask = false;
+    hstem_count = 0;
+    vstem_count = 0;
+    hintmask_size = 0;
+    pt.init ();
+    callStack.init ();
+    globalSubrs.init (globalSubrs_);
+    localSubrs.init (localSubrs_);
+  }
+  void fini ()
+  {
+    interp_env_t<ARG>::fini ();
+
+    callStack.fini ();
+    globalSubrs.fini ();
+    localSubrs.fini ();
+  }
+
+  bool in_error () const
+  {
+    return callStack.in_error () || SUPER::in_error ();
+  }
+
+  bool popSubrNum (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
+  {
+    int n = SUPER::argStack.pop_int ();
+    n += biasedSubrs.get_bias ();
+    if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ())))
+      return false;
+
+    subr_num = (unsigned int)n;
+    return true;
+  }
+
+  void callSubr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
+  {
+    unsigned int subr_num;
+
+    if (unlikely (!popSubrNum (biasedSubrs, subr_num)
+                 || callStack.get_count () >= kMaxCallLimit))
+    {
+      SUPER::set_error ();
+      return;
+    }
+    context.str_ref = SUPER::str_ref;
+    callStack.push (context);
+
+    context.init ( biasedSubrs[subr_num], type, subr_num);
+    SUPER::str_ref = context.str_ref;
+  }
+
+  void returnFromSubr ()
+  {
+    if (unlikely (SUPER::str_ref.in_error ()))
+      SUPER::set_error ();
+    context = callStack.pop ();
+    SUPER::str_ref = context.str_ref;
+  }
+
+  void determine_hintmask_size ()
+  {
+    if (!seen_hintmask)
+    {
+      vstem_count += SUPER::argStack.get_count() / 2;
+      hintmask_size = (hstem_count + vstem_count + 7) >> 3;
+      seen_hintmask = true;
+    }
+  }
+
+  void set_endchar (bool endchar_flag_) { endchar_flag = endchar_flag_; }
+  bool is_endchar () const { return endchar_flag; }
+
+  const number_t &get_x () const { return pt.x; }
+  const number_t &get_y () const { return pt.y; }
+  const point_t &get_pt () const { return pt; }
+
+  void moveto (const point_t &pt_ ) { pt = pt_; }
+
+  public:
+  call_context_t   context;
+  bool    endchar_flag;
+  bool    seen_moveto;
+  bool    seen_hintmask;
+
+  unsigned int  hstem_count;
+  unsigned int  vstem_count;
+  unsigned int  hintmask_size;
+  call_stack_t  callStack;
+  biased_subrs_t<SUBRS>   globalSubrs;
+  biased_subrs_t<SUBRS>   localSubrs;
+
+  private:
+  point_t        pt;
+
+  typedef interp_env_t<ARG> SUPER;
+};
+
+template <typename ENV, typename PARAM>
+struct path_procs_null_t
+{
+  static void rmoveto (ENV &env, PARAM& param) {}
+  static void hmoveto (ENV &env, PARAM& param) {}
+  static void vmoveto (ENV &env, PARAM& param) {}
+  static void rlineto (ENV &env, PARAM& param) {}
+  static void hlineto (ENV &env, PARAM& param) {}
+  static void vlineto (ENV &env, PARAM& param) {}
+  static void rrcurveto (ENV &env, PARAM& param) {}
+  static void rcurveline (ENV &env, PARAM& param) {}
+  static void rlinecurve (ENV &env, PARAM& param) {}
+  static void vvcurveto (ENV &env, PARAM& param) {}
+  static void hhcurveto (ENV &env, PARAM& param) {}
+  static void vhcurveto (ENV &env, PARAM& param) {}
+  static void hvcurveto (ENV &env, PARAM& param) {}
+  static void moveto (ENV &env, PARAM& param, const point_t &pt) {}
+  static void line (ENV &env, PARAM& param, const point_t &pt1) {}
+  static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) {}
+  static void hflex (ENV &env, PARAM& param) {}
+  static void flex (ENV &env, PARAM& param) {}
+  static void hflex1 (ENV &env, PARAM& param) {}
+  static void flex1 (ENV &env, PARAM& param) {}
+};
+
+template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM> >
+struct cs_opset_t : opset_t<ARG>
+{
+  static void process_op (op_code_t op, ENV &env, PARAM& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+        env.returnFromSubr ();
+        break;
+      case OpCode_endchar:
+        OPSET::check_width (op, env, param);
+        env.set_endchar (true);
+        OPSET::flush_args_and_op (op, env, param);
+        break;
+
+      case OpCode_fixedcs:
+        env.argStack.push_fixed_from_substr (env.str_ref);
+        break;
+
+      case OpCode_callsubr:
+        env.callSubr (env.localSubrs, CSType_LocalSubr);
+        break;
+
+      case OpCode_callgsubr:
+        env.callSubr (env.globalSubrs, CSType_GlobalSubr);
+        break;
+
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+        OPSET::check_width (op, env, param);
+        OPSET::process_hstem (op, env, param);
+        break;
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+        OPSET::check_width (op, env, param);
+        OPSET::process_vstem (op, env, param);
+        break;
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+        OPSET::check_width (op, env, param);
+        OPSET::process_hintmask (op, env, param);
+        break;
+      case OpCode_rmoveto:
+        OPSET::check_width (op, env, param);
+        PATH::rmoveto (env, param);
+        OPSET::process_post_move (op, env, param);
+        break;
+      case OpCode_hmoveto:
+        OPSET::check_width (op, env, param);
+        PATH::hmoveto (env, param);
+        OPSET::process_post_move (op, env, param);
+        break;
+      case OpCode_vmoveto:
+        OPSET::check_width (op, env, param);
+        PATH::vmoveto (env, param);
+        OPSET::process_post_move (op, env, param);
+        break;
+      case OpCode_rlineto:
+        PATH::rlineto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_hlineto:
+        PATH::hlineto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_vlineto:
+        PATH::vlineto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_rrcurveto:
+        PATH::rrcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_rcurveline:
+        PATH::rcurveline (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_rlinecurve:
+        PATH::rlinecurve (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_vvcurveto:
+        PATH::vvcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_hhcurveto:
+        PATH::hhcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_vhcurveto:
+        PATH::vhcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+      case OpCode_hvcurveto:
+        PATH::hvcurveto (env, param);
+        process_post_path (op, env, param);
+        break;
+
+      case OpCode_hflex:
+        PATH::hflex (env, param);
+        OPSET::process_post_flex (op, env, param);
+        break;
+
+      case OpCode_flex:
+        PATH::flex (env, param);
+        OPSET::process_post_flex (op, env, param);
+        break;
+
+      case OpCode_hflex1:
+        PATH::hflex1 (env, param);
+        OPSET::process_post_flex (op, env, param);
+        break;
+
+      case OpCode_flex1:
+        PATH::flex1 (env, param);
+        OPSET::process_post_flex (op, env, param);
+        break;
+
+      default:
+        SUPER::process_op (op, env);
+        break;
+    }
+  }
+
+  static void process_hstem (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.hstem_count += env.argStack.get_count () / 2;
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_vstem (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.vstem_count += env.argStack.get_count () / 2;
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_hintmask (op_code_t op, ENV &env, PARAM& param)
+  {
+    env.determine_hintmask_size ();
+    if (likely (env.str_ref.avail (env.hintmask_size)))
+    {
+      OPSET::flush_hintmask (op, env, param);
+      env.str_ref.inc (env.hintmask_size);
+    }
+  }
+
+  static void process_post_flex (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void check_width (op_code_t op, ENV &env, PARAM& param)
+  {}
+
+  static void process_post_move (op_code_t op, ENV &env, PARAM& param)
+  {
+    if (!env.seen_moveto)
+    {
+      env.determine_hintmask_size ();
+      env.seen_moveto = true;
+    }
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void process_post_path (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static void flush_args_and_op (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args (env, param);
+    OPSET::flush_op (op, env, param);
+  }
+
+  static void flush_args (ENV &env, PARAM& param)
+  {
+    env.pop_n_args (env.argStack.get_count ());
+  }
+
+  static void flush_op (op_code_t op, ENV &env, PARAM& param)
+  {
+  }
+
+  static void flush_hintmask (op_code_t op, ENV &env, PARAM& param)
+  {
+    OPSET::flush_args_and_op (op, env, param);
+  }
+
+  static bool is_number_op (op_code_t op)
+  {
+    switch (op)
+    {
+      case OpCode_shortint:
+      case OpCode_fixedcs:
+      case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
+      case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
+      case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
+      case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
+        return true;
+
+      default:
+        /* 1-byte integer */
+        return (OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast);
+    }
+  }
+
+  protected:
+  typedef opset_t<ARG>  SUPER;
+};
+
+template <typename PATH, typename ENV, typename PARAM>
+struct path_procs_t
+{
+  static void rmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    const number_t &dy = env.pop_arg ();
+    const number_t &dx = env.pop_arg ();
+    pt1.move (dx, dy);
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void hmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    pt1.move_x (env.pop_arg ());
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void vmoveto (ENV &env, PARAM& param)
+  {
+    point_t pt1 = env.get_pt ();
+    pt1.move_y (env.pop_arg ());
+    PATH::moveto (env, param, pt1);
+  }
+
+  static void rlineto (ENV &env, PARAM& param)
+  {
+    for (unsigned int i = 0; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void hlineto (ENV &env, PARAM& param)
+  {
+    point_t pt1;
+    unsigned int i = 0;
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+      pt1.move_y (env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    if (i < env.argStack.get_count ())
+    {
+      pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void vlineto (ENV &env, PARAM& param)
+  {
+    point_t pt1;
+    unsigned int i = 0;
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+      pt1.move_x (env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    if (i < env.argStack.get_count ())
+    {
+      pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void rrcurveto (ENV &env, PARAM& param)
+  {
+    for (unsigned int i = 0; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+  }
+
+  static void rcurveline (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    for (; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    for (; i + 2 <= env.argStack.get_count (); i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+  }
+
+  static void rlinecurve (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    unsigned int line_limit = (env.argStack.get_count () % 6);
+    for (; i + 2 <= line_limit; i += 2)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      PATH::line (env, param, pt1);
+    }
+    for (; i + 6 <= env.argStack.get_count (); i += 6)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (i), env.eval_arg (i+1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+  }
+
+  static void vvcurveto (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    point_t pt1 = env.get_pt ();
+    if ((env.argStack.get_count () & 1) != 0)
+      pt1.move_x (env.eval_arg (i++));
+    for (; i + 4 <= env.argStack.get_count (); i += 4)
+    {
+      pt1.move_y (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_y (env.eval_arg (i+3));
+      PATH::curve (env, param, pt1, pt2, pt3);
+      pt1 = env.get_pt ();
+    }
+  }
+
+  static void hhcurveto (ENV &env, PARAM& param)
+  {
+    unsigned int i = 0;
+    point_t pt1 = env.get_pt ();
+    if ((env.argStack.get_count () & 1) != 0)
+      pt1.move_y (env.eval_arg (i++));
+    for (; i + 4 <= env.argStack.get_count (); i += 4)
+    {
+      pt1.move_x (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (i+3));
+      PATH::curve (env, param, pt1, pt2, pt3);
+      pt1 = env.get_pt ();
+    }
+  }
+
+  static void vhcurveto (ENV &env, PARAM& param)
+  {
+    point_t pt1, pt2, pt3;
+    unsigned int i = 0;
+    if ((env.argStack.get_count () % 8) >= 4)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_y (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (i+3));
+      i += 4;
+
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+        PATH::curve (env, param, pt1, pt2, pt3);
+        pt1 = env.get_pt ();
+        pt1.move_x (env.eval_arg (i));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+        pt3 = pt2;
+        pt3.move_y (env.eval_arg (i+3));
+        PATH::curve (env, param, pt1, pt2, pt3);
+
+        pt1 = pt3;
+        pt1.move_y (env.eval_arg (i+4));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+        pt3 = pt2;
+        pt3.move_x (env.eval_arg (i+7));
+      }
+      if (i < env.argStack.get_count ())
+        pt3.move_y (env.eval_arg (i));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    else
+    {
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+        pt1 = env.get_pt ();
+        pt1.move_y (env.eval_arg (i));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+        pt3 = pt2;
+        pt3.move_x (env.eval_arg (i+3));
+        PATH::curve (env, param, pt1, pt2, pt3);
+
+        pt1 = pt3;
+        pt1.move_x (env.eval_arg (i+4));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+        pt3 = pt2;
+        pt3.move_y (env.eval_arg (i+7));
+        if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0))
+          pt3.move_x (env.eval_arg (i+8));
+        PATH::curve (env, param, pt1, pt2, pt3);
+      }
+    }
+  }
+
+  static void hvcurveto (ENV &env, PARAM& param)
+  {
+    point_t pt1, pt2, pt3;
+    unsigned int i = 0;
+    if ((env.argStack.get_count () % 8) >= 4)
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (i));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+      point_t pt3 = pt2;
+      pt3.move_y (env.eval_arg (i+3));
+      i += 4;
+
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+        PATH::curve (env, param, pt1, pt2, pt3);
+        pt1 = env.get_pt ();
+        pt1.move_y (env.eval_arg (i));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+        pt3 = pt2;
+        pt3.move_x (env.eval_arg (i+3));
+        PATH::curve (env, param, pt1, pt2, pt3);
+
+        pt1 = pt3;
+        pt1.move_x (env.eval_arg (i+4));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+        pt3 = pt2;
+        pt3.move_y (env.eval_arg (i+7));
+      }
+      if (i < env.argStack.get_count ())
+        pt3.move_x (env.eval_arg (i));
+      PATH::curve (env, param, pt1, pt2, pt3);
+    }
+    else
+    {
+      for (; i + 8 <= env.argStack.get_count (); i += 8)
+      {
+        pt1 = env.get_pt ();
+        pt1.move_x (env.eval_arg (i));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
+        pt3 = pt2;
+        pt3.move_y (env.eval_arg (i+3));
+        PATH::curve (env, param, pt1, pt2, pt3);
+
+        pt1 = pt3;
+        pt1.move_y (env.eval_arg (i+4));
+        pt2 = pt1;
+        pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
+        pt3 = pt2;
+        pt3.move_x (env.eval_arg (i+7));
+        if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0))
+          pt3.move_y (env.eval_arg (i+8));
+        PATH::curve (env, param, pt1, pt2, pt3);
+      }
+    }
+  }
+
+  /* default actions to be overridden */
+  static void moveto (ENV &env, PARAM& param, const point_t &pt)
+  { env.moveto (pt); }
+
+  static void line (ENV &env, PARAM& param, const point_t &pt1)
+  { PATH::moveto (env, param, pt1); }
+
+  static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  { PATH::moveto (env, param, pt3); }
+
+  static void hflex (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 7))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move_x (env.eval_arg (0));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (1), env.eval_arg (2));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (3));
+      point_t pt4 = pt3;
+      pt4.move_x (env.eval_arg (4));
+      point_t pt5 = pt4;
+      pt5.move_x (env.eval_arg (5));
+      pt5.y = pt1.y;
+      point_t pt6 = pt5;
+      pt6.move_x (env.eval_arg (6));
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void flex (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 13))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (4), env.eval_arg (5));
+      point_t pt4 = pt3;
+      pt4.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (8), env.eval_arg (9));
+      point_t pt6 = pt5;
+      pt6.move (env.eval_arg (10), env.eval_arg (11));
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void hflex1 (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 9))
+    {
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move_x (env.eval_arg (4));
+      point_t pt4 = pt3;
+      pt4.move_x (env.eval_arg (5));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt6 = pt5;
+      pt6.move_x (env.eval_arg (8));
+      pt6.y = env.get_pt ().y;
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  static void flex1 (ENV &env, PARAM& param)
+  {
+    if (likely (env.argStack.get_count () == 11))
+    {
+      point_t d;
+      d.init ();
+      for (unsigned int i = 0; i < 10; i += 2)
+        d.move (env.eval_arg (i), env.eval_arg (i+1));
+
+      point_t pt1 = env.get_pt ();
+      pt1.move (env.eval_arg (0), env.eval_arg (1));
+      point_t pt2 = pt1;
+      pt2.move (env.eval_arg (2), env.eval_arg (3));
+      point_t pt3 = pt2;
+      pt3.move (env.eval_arg (4), env.eval_arg (5));
+      point_t pt4 = pt3;
+      pt4.move (env.eval_arg (6), env.eval_arg (7));
+      point_t pt5 = pt4;
+      pt5.move (env.eval_arg (8), env.eval_arg (9));
+      point_t pt6 = pt5;
+
+      if (fabs (d.x.to_real ()) > fabs (d.y.to_real ()))
+      {
+        pt6.move_x (env.eval_arg (10));
+        pt6.y = env.get_pt ().y;
+      }
+      else
+      {
+        pt6.x = env.get_pt ().x;
+        pt6.move_y (env.eval_arg (10));
+      }
+
+      curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6);
+    }
+    else
+      env.set_error ();
+  }
+
+  protected:
+  static void curve2 (ENV &env, PARAM& param,
+                      const point_t &pt1, const point_t &pt2, const point_t &pt3,
+                      const point_t &pt4, const point_t &pt5, const point_t &pt6)
+  {
+    PATH::curve (env, param, pt1, pt2, pt3);
+    PATH::curve (env, param, pt4, pt5, pt6);
+  }
+};
+
+template <typename ENV, typename OPSET, typename PARAM>
+struct cs_interpreter_t : interpreter_t<ENV>
+{
+  bool interpret (PARAM& param)
+  {
+    SUPER::env.set_endchar (false);
+
+    for (;;) {
+      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
+      if (unlikely (SUPER::env.in_error ()))
+        return false;
+      if (SUPER::env.is_endchar ())
+        break;
+    }
+
+    return true;
+  }
+
+  private:
+  typedef interpreter_t<ENV> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_CS_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff-interp-dict-common.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,294 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF_INTERP_DICT_COMMON_HH
+#define HB_CFF_INTERP_DICT_COMMON_HH
+
+#include "hb-cff-interp-common.hh"
+#include <math.h>
+#include <float.h>
+
+namespace CFF {
+
+using namespace OT;
+
+/* an opstr and the parsed out dict value(s) */
+struct dict_val_t : op_str_t
+{
+  void init () { single_val.set_int (0); }
+  void fini () {}
+
+  number_t            single_val;
+};
+
+typedef dict_val_t num_dict_val_t;
+
+template <typename VAL> struct dict_values_t : parsed_values_t<VAL> {};
+
+template <typename OPSTR=op_str_t>
+struct top_dict_values_t : dict_values_t<OPSTR>
+{
+  void init ()
+  {
+    dict_values_t<OPSTR>::init ();
+    charStringsOffset = 0;
+    FDArrayOffset = 0;
+  }
+  void fini () { dict_values_t<OPSTR>::fini (); }
+
+  unsigned int calculate_serialized_op_size (const OPSTR& opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+      case OpCode_FDArray:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+        return opstr.str.length;
+    }
+  }
+
+  unsigned int  charStringsOffset;
+  unsigned int  FDArrayOffset;
+};
+
+struct dict_opset_t : opset_t<number_t>
+{
+  static void process_op (op_code_t op, interp_env_t<number_t>& env)
+  {
+    switch (op) {
+      case OpCode_longintdict:  /* 5-byte integer */
+        env.argStack.push_longint_from_substr (env.str_ref);
+        break;
+
+      case OpCode_BCD:  /* real number */
+        env.argStack.push_real (parse_bcd (env.str_ref));
+        break;
+
+      default:
+        opset_t<number_t>::process_op (op, env);
+        break;
+    }
+  }
+
+  static double parse_bcd (byte_str_ref_t& str_ref)
+  {
+    bool    neg = false;
+    double  int_part = 0;
+    uint64_t frac_part = 0;
+    uint32_t  frac_count = 0;
+    bool    exp_neg = false;
+    uint32_t  exp_part = 0;
+    bool    exp_overflow = false;
+    enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART;
+    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
+    const uint64_t MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */
+    const uint32_t MAX_EXP = 0x7FFu; /* 1^11-1 */
+
+    double  value = 0.0;
+    unsigned char byte = 0;
+    for (uint32_t i = 0;; i++)
+    {
+      char d;
+      if ((i & 1) == 0)
+      {
+        if (!str_ref.avail ())
+        {
+          str_ref.set_error ();
+          return 0.0;
+        }
+        byte = str_ref[0];
+        str_ref.inc ();
+        d = byte >> 4;
+      }
+      else
+        d = byte & 0x0F;
+
+      switch (d)
+      {
+        case RESERVED:
+          str_ref.set_error ();
+          return value;
+
+        case END:
+          value = (double)(neg? -int_part: int_part);
+          if (frac_count > 0)
+          {
+            double frac = (frac_part / pow (10.0, (double)frac_count));
+            if (neg) frac = -frac;
+            value += frac;
+          }
+          if (unlikely (exp_overflow))
+          {
+            if (value == 0.0)
+              return value;
+            if (exp_neg)
+              return neg? -DBL_MIN: DBL_MIN;
+            else
+              return neg? -DBL_MAX: DBL_MAX;
+          }
+          if (exp_part != 0)
+          {
+            if (exp_neg)
+              value /= pow (10.0, (double)exp_part);
+            else
+              value *= pow (10.0, (double)exp_part);
+          }
+          return value;
+
+        case NEG:
+          if (i != 0)
+          {
+            str_ref.set_error ();
+            return 0.0;
+          }
+          neg = true;
+          break;
+
+        case DECIMAL:
+          if (part != INT_PART)
+          {
+            str_ref.set_error ();
+            return value;
+          }
+          part = FRAC_PART;
+          break;
+
+        case EXP_NEG:
+          exp_neg = true;
+          HB_FALLTHROUGH;
+
+        case EXP_POS:
+          if (part == EXP_PART)
+          {
+            str_ref.set_error ();
+            return value;
+          }
+          part = EXP_PART;
+          break;
+
+        default:
+          switch (part) {
+            default:
+            case INT_PART:
+              int_part = (int_part * 10) + d;
+              break;
+
+            case FRAC_PART:
+              if (likely (frac_part <= MAX_FRACT / 10))
+              {
+                frac_part = (frac_part * 10) + (unsigned)d;
+                frac_count++;
+              }
+              break;
+
+            case EXP_PART:
+              if (likely (exp_part * 10 + d <= MAX_EXP))
+              {
+                exp_part = (exp_part * 10) + d;
+              }
+              else
+                exp_overflow = true;
+              break;
+          }
+      }
+    }
+
+    return value;
+  }
+
+  static bool is_hint_op (op_code_t op)
+  {
+    switch (op)
+    {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+        return true;
+      default:
+        return false;
+    }
+  }
+};
+
+template <typename VAL=op_str_t>
+struct top_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, interp_env_t<number_t>& env, top_dict_values_t<VAL> & dictval)
+  {
+    switch (op) {
+      case OpCode_CharStrings:
+        dictval.charStringsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_FDArray:
+        dictval.FDArrayOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_FontMatrix:
+        env.clear_args ();
+        break;
+      default:
+        dict_opset_t::process_op (op, env);
+        break;
+    }
+  }
+};
+
+template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
+struct dict_interpreter_t : interpreter_t<ENV>
+{
+  bool interpret (PARAM& param)
+  {
+    param.init ();
+    while (SUPER::env.str_ref.avail ())
+    {
+      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
+      if (unlikely (SUPER::env.in_error ()))
+        return false;
+    }
+
+    return true;
+  }
+
+  private:
+  typedef interpreter_t<ENV> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF_INTERP_DICT_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff1-interp-cs.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF1_INTERP_CS_HH
+#define HB_CFF1_INTERP_CS_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+typedef biased_subrs_t<CFF1Subrs>   cff1_biased_subrs_t;
+
+struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
+{
+  template <typename ACC>
+  void init (const byte_str_t &str, ACC &acc, unsigned int fd)
+  {
+    SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
+    processed_width = false;
+    has_width = false;
+    arg_start = 0;
+    in_seac = false;
+  }
+
+  void fini () { SUPER::fini (); }
+
+  void set_width (bool has_width_)
+  {
+    if (likely (!processed_width && (SUPER::argStack.get_count () > 0)))
+    {
+      if (has_width_)
+      {
+        width = SUPER::argStack[0];
+        has_width = true;
+        arg_start = 1;
+      }
+    }
+    processed_width = true;
+  }
+
+  void clear_args ()
+  {
+    arg_start = 0;
+    SUPER::clear_args ();
+  }
+
+  void set_in_seac (bool _in_seac) { in_seac = _in_seac; }
+
+  bool    processed_width;
+  bool    has_width;
+  unsigned int  arg_start;
+  number_t      width;
+  bool    in_seac;
+
+  private:
+  typedef cs_interp_env_t<number_t, CFF1Subrs> SUPER;
+};
+
+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM> >
+struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>
+{
+  /* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */
+  /* Type 1-originated deprecated opcodes, seac behavior of endchar and dotsection are supported */
+
+  static void process_op (op_code_t op, cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    switch (op) {
+      case OpCode_dotsection:
+        SUPER::flush_args_and_op (op, env, param);
+        break;
+
+      case OpCode_endchar:
+        OPSET::check_width (op, env, param);
+        if (env.argStack.get_count () >= 4)
+        {
+          OPSET::process_seac (env, param);
+        }
+        OPSET::flush_args_and_op (op, env, param);
+        env.set_endchar (true);
+        break;
+
+      default:
+        SUPER::process_op (op, env, param);
+    }
+  }
+
+  static void check_width (op_code_t op, cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    if (!env.processed_width)
+    {
+      bool  has_width = false;
+      switch (op)
+      {
+        case OpCode_endchar:
+        case OpCode_hstem:
+        case OpCode_hstemhm:
+        case OpCode_vstem:
+        case OpCode_vstemhm:
+        case OpCode_hintmask:
+        case OpCode_cntrmask:
+          has_width = ((env.argStack.get_count () & 1) != 0);
+          break;
+        case OpCode_hmoveto:
+        case OpCode_vmoveto:
+          has_width = (env.argStack.get_count () > 1);
+          break;
+        case OpCode_rmoveto:
+          has_width = (env.argStack.get_count () > 2);
+          break;
+        default:
+          return;
+      }
+      env.set_width (has_width);
+    }
+  }
+
+  static void process_seac (cff1_cs_interp_env_t &env, PARAM& param)
+  {
+  }
+
+  static void flush_args (cff1_cs_interp_env_t &env, PARAM& param)
+  {
+    SUPER::flush_args (env, param);
+    env.clear_args ();  /* pop off width */
+  }
+
+  private:
+  typedef cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>  SUPER;
+};
+
+template <typename OPSET, typename PARAM>
+struct cff1_cs_interpreter_t : cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM> {};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF1_INTERP_CS_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-cff2-interp-cs.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,271 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_CFF2_INTERP_CS_HH
+#define HB_CFF2_INTERP_CS_HH
+
+#include "hb.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+struct blend_arg_t : number_t
+{
+  void init ()
+  {
+    number_t::init ();
+    deltas.init ();
+  }
+
+  void fini ()
+  {
+    number_t::fini ();
+    deltas.fini_deep ();
+  }
+
+  void set_int (int v) { reset_blends (); number_t::set_int (v); }
+  void set_fixed (int32_t v) { reset_blends (); number_t::set_fixed (v); }
+  void set_real (double v) { reset_blends (); number_t::set_real (v); }
+
+  void set_blends (unsigned int numValues_, unsigned int valueIndex_,
+                          unsigned int numBlends, hb_array_t<const blend_arg_t> blends_)
+  {
+    numValues = numValues_;
+    valueIndex = valueIndex_;
+    deltas.resize (numBlends);
+    for (unsigned int i = 0; i < numBlends; i++)
+      deltas[i] = blends_[i];
+  }
+
+  bool blending () const { return deltas.length > 0; }
+  void reset_blends ()
+  {
+    numValues = valueIndex = 0;
+    deltas.resize (0);
+  }
+
+  unsigned int numValues;
+  unsigned int valueIndex;
+  hb_vector_t<number_t> deltas;
+};
+
+typedef interp_env_t<blend_arg_t> BlendInterpEnv;
+typedef biased_subrs_t<CFF2Subrs>   cff2_biased_subrs_t;
+
+struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
+{
+  template <typename ACC>
+  void init (const byte_str_t &str, ACC &acc, unsigned int fd,
+                    const int *coords_=nullptr, unsigned int num_coords_=0)
+  {
+    SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
+
+    coords = coords_;
+    num_coords = num_coords_;
+    varStore = acc.varStore;
+    seen_blend = false;
+    seen_vsindex_ = false;
+    scalars.init ();
+    do_blend = (coords != nullptr) && num_coords && (varStore != &Null(CFF2VariationStore));
+    set_ivs (acc.privateDicts[fd].ivs);
+  }
+
+  void fini ()
+  {
+    scalars.fini ();
+    SUPER::fini ();
+  }
+
+  op_code_t fetch_op ()
+  {
+    if (this->str_ref.avail ())
+      return SUPER::fetch_op ();
+
+    /* make up return or endchar op */
+    if (this->callStack.is_empty ())
+      return OpCode_endchar;
+    else
+      return OpCode_return;
+  }
+
+  const blend_arg_t& eval_arg (unsigned int i)
+  {
+    blend_arg_t  &arg = argStack[i];
+    blend_arg (arg);
+    return arg;
+  }
+
+  const blend_arg_t& pop_arg ()
+  {
+    blend_arg_t  &arg = argStack.pop ();
+    blend_arg (arg);
+    return arg;
+  }
+
+  void process_blend ()
+  {
+    if (!seen_blend)
+    {
+      region_count = varStore->varStore.get_region_index_count (get_ivs ());
+      if (do_blend)
+      {
+        scalars.resize (region_count);
+        varStore->varStore.get_scalars (get_ivs (),
+                                        (int *)coords, num_coords,
+                                        &scalars[0], region_count);
+      }
+      seen_blend = true;
+    }
+  }
+
+  void process_vsindex ()
+  {
+    unsigned int  index = argStack.pop_uint ();
+    if (unlikely (seen_vsindex () || seen_blend))
+    {
+      set_error ();
+    }
+    else
+    {
+      set_ivs (index);
+    }
+    seen_vsindex_ = true;
+  }
+
+  unsigned int get_region_count () const { return region_count; }
+  void   set_region_count (unsigned int region_count_) { region_count = region_count_; }
+  unsigned int get_ivs () const { return ivs; }
+  void   set_ivs (unsigned int ivs_) { ivs = ivs_; }
+  bool   seen_vsindex () const { return seen_vsindex_; }
+
+  protected:
+  void blend_arg (blend_arg_t &arg)
+  {
+    if (do_blend && arg.blending ())
+    {
+      if (likely (scalars.length == arg.deltas.length))
+      {
+        double v = arg.to_real ();
+        for (unsigned int i = 0; i < scalars.length; i++)
+        {
+          v += (double)scalars[i] * arg.deltas[i].to_real ();
+        }
+        arg.set_real (v);
+        arg.deltas.resize (0);
+      }
+    }
+  }
+
+  protected:
+  const int     *coords;
+  unsigned int  num_coords;
+  const  CFF2VariationStore *varStore;
+  unsigned int  region_count;
+  unsigned int  ivs;
+  hb_vector_t<float>  scalars;
+  bool    do_blend;
+  bool    seen_vsindex_;
+  bool    seen_blend;
+
+  typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
+};
+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM> >
+struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
+{
+  static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    switch (op) {
+      case OpCode_callsubr:
+      case OpCode_callgsubr:
+        /* a subroutine number shoudln't be a blended value */
+        if (unlikely (env.argStack.peek ().blending ()))
+        {
+          env.set_error ();
+          break;
+        }
+        SUPER::process_op (op, env, param);
+        break;
+
+      case OpCode_blendcs:
+        OPSET::process_blend (env, param);
+        break;
+
+      case OpCode_vsindexcs:
+        if (unlikely (env.argStack.peek ().blending ()))
+        {
+          env.set_error ();
+          break;
+        }
+        OPSET::process_vsindex (env, param);
+        break;
+
+      default:
+        SUPER::process_op (op, env, param);
+    }
+  }
+
+  static void process_blend (cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    unsigned int n, k;
+
+    env.process_blend ();
+    k = env.get_region_count ();
+    n = env.argStack.pop_uint ();
+    /* copy the blend values into blend array of the default values */
+    unsigned int start = env.argStack.get_count () - ((k+1) * n);
+    /* let an obvious error case fail, but note CFF2 spec doesn't forbid n==0 */
+    if (unlikely (start > env.argStack.get_count ()))
+    {
+      env.set_error ();
+      return;
+    }
+    for (unsigned int i = 0; i < n; i++)
+    {
+      const hb_array_t<const blend_arg_t>       blends = env.argStack.get_subarray (start + n + (i * k));
+      env.argStack[start + i].set_blends (n, i, k, blends);
+    }
+
+    /* pop off blend values leaving default values now adorned with blend values */
+    env.argStack.pop (k * n);
+  }
+
+  static void process_vsindex (cff2_cs_interp_env_t &env, PARAM& param)
+  {
+    env.process_vsindex ();
+    env.clear_args ();
+  }
+
+  private:
+  typedef cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>  SUPER;
+};
+
+template <typename OPSET, typename PARAM>
+struct cff2_cs_interpreter_t : cs_interpreter_t<cff2_cs_interp_env_t, OPSET, PARAM> {};
+
+} /* namespace CFF */
+
+#endif /* HB_CFF2_INTERP_CS_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,10 +26,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-mutex-private.hh"
-#include "hb-object-private.hh"
+#include "hb-machinery.hh"
 
 #include <locale.h>
 #ifdef HAVE_XLOCALE_H
@@ -37,22 +36,51 @@
 #endif
 
 
+/**
+ * SECTION:hb-common
+ * @title: hb-common
+ * @short_description: Common data types
+ * @include: hb.h
+ *
+ * Common data types used across HarfBuzz are defined here.
+ **/
+
+
 /* hb_options_t */
 
-hb_options_union_t _hb_options;
+hb_atomic_int_t _hb_options;
 
 void
-_hb_options_init (void)
+_hb_options_init ()
 {
   hb_options_union_t u;
   u.i = 0;
-  u.opts.initialized = 1;
+  u.opts.initialized = true;
+
+  const char *c = getenv ("HB_OPTIONS");
+  if (c)
+  {
+    while (*c)
+    {
+      const char *p = strchr (c, ':');
+      if (!p)
+        p = c + strlen (c);
 
-  char *c = getenv ("HB_OPTIONS");
-  u.opts.uniscribe_bug_compatible = c && strstr (c, "uniscribe-bug-compatible");
+#define OPTION(name, symbol) \
+        if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true;
+
+      OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
+      OPTION ("aat", aat);
+
+#undef OPTION
+
+      c = *p ? p + 1 : p;
+    }
+
+  }
 
   /* This is idempotent and threadsafe. */
-  _hb_options = u;
+  _hb_options.set_relaxed (u.i);
 }
 
 
@@ -176,7 +204,7 @@
    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,   0,   0,   0,
    0,   0,   0,   0,   0,   0,   0,   0,    0,   0,   0,   0,   0,  '-',  0,   0,
   '0', '1', '2', '3', '4', '5', '6', '7',  '8', '9',  0,   0,   0,   0,   0,   0,
-  '-', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+   0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,  '-',
    0,  'a', 'b', 'c', 'd', 'e', 'f', 'g',  'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
   'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  'x', 'y', 'z',  0,   0,   0,   0,   0
@@ -219,11 +247,10 @@
   struct hb_language_item_t *next;
   hb_language_t lang;
 
-  inline bool operator == (const char *s) const {
-    return lang_equal (lang, s);
-  }
+  bool operator == (const char *s) const
+  { return lang_equal (lang, s); }
 
-  inline hb_language_item_t & operator = (const char *s) {
+  hb_language_item_t & operator = (const char *s) {
     /* If a custom allocated is used calling strdup() pairs
     badly with a call to the custom free() in fini() below.
     Therefore don't call strdup(), implement its behavior.
@@ -240,21 +267,21 @@
     return *this;
   }
 
-  void fini (void) { free ((void *) lang); }
+  void fini () { free ((void *) lang); }
 };
 
 
 /* Thread-safe lock-free language list */
 
-static hb_language_item_t *langs;
+static hb_atomic_ptr_t <hb_language_item_t> langs;
 
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
 static void
-free_langs (void)
+free_langs ()
 {
 retry:
-  hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
-  if (!hb_atomic_ptr_cmpexch (&langs, first_lang, nullptr))
+  hb_language_item_t *first_lang = langs;
+  if (unlikely (!langs.cmpexch (first_lang, nullptr)))
     goto retry;
 
   while (first_lang) {
@@ -270,7 +297,7 @@
 lang_find_or_insert (const char *key)
 {
 retry:
-  hb_language_item_t *first_lang = (hb_language_item_t *) hb_atomic_ptr_get (&langs);
+  hb_language_item_t *first_lang = langs;
 
   for (hb_language_item_t *lang = first_lang; lang; lang = lang->next)
     if (*lang == key)
@@ -288,13 +315,14 @@
     return nullptr;
   }
 
-  if (!hb_atomic_ptr_cmpexch (&langs, first_lang, lang)) {
+  if (unlikely (!langs.cmpexch (first_lang, lang)))
+  {
     lang->fini ();
     free (lang);
     goto retry;
   }
 
-#ifdef HB_USE_ATEXIT
+#if HB_USE_ATEXIT
   if (!first_lang)
     atexit (free_langs); /* First person registers atexit() callback. */
 #endif
@@ -306,14 +334,14 @@
 /**
  * hb_language_from_string:
  * @str: (array length=len) (element-type uint8_t): a string representing
- *       ISO 639 language code
+ *       a BCP 47 language tag
  * @len: length of the @str, or -1 if it is %NULL-terminated.
  *
- * Converts @str representing an ISO 639 language code to the corresponding
+ * Converts @str representing a BCP 47 language tag to the corresponding
  * #hb_language_t.
  *
  * Return value: (transfer none):
- * The #hb_language_t corresponding to the ISO 639 language code.
+ * The #hb_language_t corresponding to the BCP 47 language tag.
  *
  * Since: 0.9.2
  **/
@@ -361,24 +389,32 @@
 /**
  * hb_language_get_default:
  *
+ * Get default language from current locale.
  *
+ * Note that the first time this function is called, it calls
+ * "setlocale (LC_CTYPE, nullptr)" to fetch current locale.  The underlying
+ * setlocale function is, in many implementations, NOT threadsafe.  To avoid
+ * problems, call this function once before multiple threads can call it.
+ * This function is only used from hb_buffer_guess_segment_properties() by
+ * HarfBuzz itself.
  *
  * Return value: (transfer none):
  *
  * Since: 0.9.2
  **/
 hb_language_t
-hb_language_get_default (void)
+hb_language_get_default ()
 {
-  static hb_language_t default_language = HB_LANGUAGE_INVALID;
+  static hb_atomic_ptr_t <hb_language_t> default_language;
 
-  hb_language_t language = (hb_language_t) hb_atomic_ptr_get (&default_language);
-  if (unlikely (language == HB_LANGUAGE_INVALID)) {
+  hb_language_t language = default_language;
+  if (unlikely (language == HB_LANGUAGE_INVALID))
+  {
     language = hb_language_from_string (setlocale (LC_CTYPE, nullptr), -1);
-    (void) hb_atomic_ptr_cmpexch (&default_language, HB_LANGUAGE_INVALID, language);
+    (void) default_language.cmpexch (HB_LANGUAGE_INVALID, language);
   }
 
-  return default_language;
+  return language;
 }
 
 
@@ -530,7 +566,6 @@
 
     /* Unicode-8.0 additions */
     case HB_SCRIPT_HATRAN:
-    case HB_SCRIPT_OLD_HUNGARIAN:
 
     /* Unicode-9.0 additions */
     case HB_SCRIPT_ADLAM:
@@ -544,7 +579,9 @@
 
 
     /* https://github.com/harfbuzz/harfbuzz/issues/1000 */
+    case HB_SCRIPT_OLD_HUNGARIAN:
     case HB_SCRIPT_OLD_ITALIC:
+    case HB_SCRIPT_RUNIC:
 
       return HB_DIRECTION_INVALID;
   }
@@ -587,6 +624,19 @@
 
 /* hb_version */
 
+
+/**
+ * SECTION:hb-version
+ * @title: hb-version
+ * @short_description: Information about the version of HarfBuzz in use
+ * @include: hb.h
+ *
+ * These functions and macros allow accessing version of the HarfBuzz
+ * library used at compile- as well as run-time, and to direct code
+ * conditionally based on those versions, again, at compile- or run-time.
+ **/
+
+
 /**
  * hb_version:
  * @major: (out): Library major version component.
@@ -617,7 +667,7 @@
  * Since: 0.9.2
  **/
 const char *
-hb_version_string (void)
+hb_version_string ()
 {
   return HB_VERSION_STRING;
 }
@@ -729,47 +779,47 @@
 
 #ifdef USE_XLOCALE
 
-static HB_LOCALE_T C_locale;
+#if HB_USE_ATEXIT
+static void free_static_C_locale ();
+#endif
 
-#ifdef HB_USE_ATEXIT
-static void
-free_C_locale (void)
+static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (HB_LOCALE_T),
+                                                          hb_C_locale_lazy_loader_t>
 {
-retry:
-  HB_LOCALE_T locale = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
+  static HB_LOCALE_T create ()
+  {
+    HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
+
+#if HB_USE_ATEXIT
+    atexit (free_static_C_locale);
+#endif
 
-  if (!hb_atomic_ptr_cmpexch (&C_locale, locale, nullptr))
-    goto retry;
+    return C_locale;
+  }
+  static void destroy (HB_LOCALE_T p)
+  {
+    HB_FREE_LOCALE (p);
+  }
+  static HB_LOCALE_T get_null ()
+  {
+    return nullptr;
+  }
+} static_C_locale;
 
-  if (locale)
-    HB_FREE_LOCALE (locale);
+#if HB_USE_ATEXIT
+static
+void free_static_C_locale ()
+{
+  static_C_locale.free_instance ();
 }
 #endif
 
 static HB_LOCALE_T
-get_C_locale (void)
+get_C_locale ()
 {
-retry:
-  HB_LOCALE_T C = (HB_LOCALE_T) hb_atomic_ptr_get (&C_locale);
-
-  if (unlikely (!C))
-  {
-    C = HB_CREATE_LOCALE ("C");
-
-    if (!hb_atomic_ptr_cmpexch (&C_locale, nullptr, C))
-    {
-      HB_FREE_LOCALE (C_locale);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_C_locale); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return C;
+  return static_C_locale.get_unconst ();
 }
-#endif
+#endif /* USE_XLOCALE */
 
 static bool
 parse_float (const char **pp, const char *end, float *pv)
@@ -846,7 +896,7 @@
   }
 
   const char *p = *pp;
-  while (*pp < end && ISALNUM(**pp))
+  while (*pp < end && (ISALNUM(**pp) || **pp == '_'))
     (*pp)++;
 
   if (p == *pp || *pp - p > 4)
@@ -875,15 +925,15 @@
 
   bool has_start;
 
-  feature->start = 0;
-  feature->end = (unsigned int) -1;
+  feature->start = HB_FEATURE_GLOBAL_START;
+  feature->end = HB_FEATURE_GLOBAL_END;
 
   if (!parse_char (pp, end, '['))
     return true;
 
   has_start = parse_uint (pp, end, &feature->start);
 
-  if (parse_char (pp, end, ':')) {
+  if (parse_char (pp, end, ':') || parse_char (pp, end, ';')) {
     parse_uint (pp, end, &feature->end);
   } else {
     if (has_start)
@@ -1063,10 +1113,19 @@
   while (len && s[len - 1] == ' ')
     len--;
   s[len++] = '=';
-  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", variation->value));
+  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
 
   assert (len < ARRAY_LENGTH (s));
   len = MIN (len, size - 1);
   memcpy (buf, s, len);
   buf[len] = '\0';
 }
+
+/* If there is no visibility control, then hb-static.cc will NOT
+ * define anything.  Instead, we get it to define one set in here
+ * only, so only libharfbuzz.so defines them, not other libs. */
+#ifdef HB_NO_VISIBILITY
+#undef HB_NO_VISIBILITY
+#include "hb-static.cc"
+#define HB_NO_VISIBILITY 1
+#endif
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-common.h	Tue Mar 26 09:05:10 2019 -0400
@@ -33,6 +33,10 @@
 #ifndef HB_COMMON_H
 #define HB_COMMON_H
 
+#ifndef HB_EXTERN
+#define HB_EXTERN extern
+#endif
+
 #ifndef HB_BEGIN_DECLS
 # ifdef __cplusplus
 #  define HB_BEGIN_DECLS        extern "C" {
@@ -63,6 +67,23 @@
 #  include <stdint.h>
 #endif
 
+#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define HB_DEPRECATED __attribute__((__deprecated__))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
+#define HB_DEPRECATED __declspec(deprecated)
+#else
+#define HB_DEPRECATED
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#define HB_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead")))
+#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER > 140050320)
+#define HB_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead"))
+#else
+#define HB_DEPRECATED_FOR(f) HB_DEPRECATED
+#endif
+
+
 HB_BEGIN_DECLS
 
 
@@ -86,8 +107,8 @@
 
 typedef uint32_t hb_tag_t;
 
-#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint8_t)(c1))<<24)|(((uint8_t)(c2))<<16)|(((uint8_t)(c3))<<8)|((uint8_t)(c4))))
-#define HB_UNTAG(tag)   ((uint8_t)((tag)>>24)), ((uint8_t)((tag)>>16)), ((uint8_t)((tag)>>8)), ((uint8_t)(tag))
+#define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF)))
+#define HB_UNTAG(tag)   (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF)
 
 #define HB_TAG_NONE HB_TAG(0,0,0,0)
 #define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff)
@@ -340,13 +361,15 @@
   HB_SCRIPT_INVALID                             = HB_TAG_NONE,
 
   /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t
-   * without risking undefined behavior.  Include both a signed and unsigned max,
-   * since technically enums are int, and indeed, hb_script_t ends up being signed.
+   * without risking undefined behavior.  We have two, for historical reasons.
+   * HB_TAG_MAX used to be unsigned, but that was invalid Ansi C, so was changed
+   * to _HB_SCRIPT_MAX_VALUE to be equal to HB_TAG_MAX_SIGNED as well.
+   *
    * See this thread for technicalities:
    *
    *   https://lists.freedesktop.org/archives/harfbuzz/2014-March/004150.html
    */
-  _HB_SCRIPT_MAX_VALUE                          = HB_TAG_MAX, /*< skip >*/
+  _HB_SCRIPT_MAX_VALUE                          = HB_TAG_MAX_SIGNED, /*< skip >*/
   _HB_SCRIPT_MAX_VALUE_SIGNED                   = HB_TAG_MAX_SIGNED /*< skip >*/
 
 } hb_script_t;
@@ -379,6 +402,19 @@
 
 /* Font features and variations. */
 
+/**
+ * HB_FEATURE_GLOBAL_START
+ *
+ * Since: 2.0.0
+ */
+#define HB_FEATURE_GLOBAL_START 0
+/**
+ * HB_FEATURE_GLOBAL_END
+ *
+ * Since: 2.0.0
+ */
+#define HB_FEATURE_GLOBAL_END   ((unsigned int) -1)
+
 typedef struct hb_feature_t {
   hb_tag_t      tag;
   uint32_t      value;
@@ -412,6 +448,50 @@
 hb_variation_to_string (hb_variation_t *variation,
                         char *buf, unsigned int size);
 
+/**
+ * hb_color_t:
+ *
+ * Data type for holding color values.
+ *
+ * Since: 2.1.0
+ */
+typedef uint32_t hb_color_t;
+
+#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
+
+/**
+ * hb_color_get_alpha:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_alpha(color)       ((color) & 0xFF)
+/**
+ * hb_color_get_red:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_red(color)         (((color) >> 8) & 0xFF)
+/**
+ * hb_color_get_green:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_green(color)       (((color) >> 16) & 0xFF)
+/**
+ * hb_color_get_blue:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
+#define hb_color_get_blue(color)        (((color) >> 24) & 0xFF)
+
 
 HB_END_DECLS
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,15 +26,23 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER coretext
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-shaper-impl-private.hh"
+#include "hb.hh"
+#include "hb-shaper-impl.hh"
 
 #include "hb-coretext.h"
+#include "hb-aat-layout.hh"
 #include <math.h>
 
+
+/**
+ * SECTION:hb-coretext
+ * @title: hb-coretext
+ * @short_description: CoreText integration
+ * @include: hb-coretext.h
+ *
+ * Functions for using HarfBuzz with the CoreText fonts.
+ **/
+
 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
 
@@ -91,13 +99,8 @@
 }
 
 
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
-HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
-        fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
-)
-
 static CTFontDescriptorRef
-get_last_resort_font_desc (void)
+get_last_resort_font_desc ()
 {
   // TODO Handle allocation failures?
   CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
@@ -211,7 +214,7 @@
   }
 
   CFURLRef original_url = nullptr;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
   ATSFontRef atsFont;
   FSRef fsref;
   OSStatus status;
@@ -241,7 +244,7 @@
        * process in Blink. This can be detected by the new file URL location
        * that the newly found font points to. */
       CFURLRef new_url = nullptr;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
       atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
       status = ATSFontGetFileReference (atsFont, &fsref);
       if (status == noErr)
@@ -270,7 +273,7 @@
   return ct_font;
 }
 
-hb_coretext_shaper_face_data_t *
+hb_coretext_face_data_t *
 _hb_coretext_shaper_face_data_create (hb_face_t *face)
 {
   CGFontRef cg_font = create_cg_font (face);
@@ -281,11 +284,11 @@
     return nullptr;
   }
 
-  return (hb_coretext_shaper_face_data_t *) cg_font;
+  return (hb_coretext_face_data_t *) cg_font;
 }
 
 void
-_hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
+_hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
 {
   CFRelease ((CGFontRef) data);
 }
@@ -302,17 +305,17 @@
 CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face)
 {
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  return (CGFontRef) HB_SHAPER_DATA_GET (face);
+  return (CGFontRef) (const void *) face->data.coretext;
 }
 
 
-hb_coretext_shaper_font_data_t *
+hb_coretext_font_data_t *
 _hb_coretext_shaper_font_data_create (hb_font_t *font)
 {
   hb_face_t *face = font->face;
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
+  const hb_coretext_face_data_t *face_data = face->data.coretext;
+  if (unlikely (!face_data)) return nullptr;
+  CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
 
   CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
 
@@ -322,15 +325,47 @@
     return nullptr;
   }
 
-  return (hb_coretext_shaper_font_data_t *) ct_font;
+  return (hb_coretext_font_data_t *) ct_font;
 }
 
 void
-_hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
+_hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
 {
   CFRelease ((CTFontRef) data);
 }
 
+static const hb_coretext_font_data_t *
+hb_coretext_font_data_sync (hb_font_t *font)
+{
+retry:
+  const hb_coretext_font_data_t *data = font->data.coretext;
+  if (unlikely (!data)) return nullptr;
+
+  if (fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) > .5)
+  {
+    /* XXX-MT-bug
+     * Note that evaluating condition above can be dangerous if another thread
+     * got here first and destructed data.  That's, as always, bad use pattern.
+     * If you modify the font (change font size), other threads must not be
+     * using it at the same time.  However, since this check is delayed to
+     * when one actually tries to shape something, this is a XXX race condition
+     * (and the only one we have that I know of) right now.  Ie. you modify the
+     * font size in one thread, then (supposedly safely) try to use it from two
+     * or more threads and BOOM!  I'm not sure how to fix this.  We want RCU.
+     */
+
+    /* Drop and recreate. */
+    /* If someone dropped it in the mean time, throw it away and don't touch it.
+     * Otherwise, destruct it. */
+    if (likely (font->data.coretext.cmpexch (const_cast<hb_coretext_font_data_t *> (data), nullptr)))
+      _hb_coretext_shaper_font_data_destroy (const_cast<hb_coretext_font_data_t *> (data));
+    else
+      goto retry;
+  }
+  return font->data.coretext;
+}
+
+
 /*
  * Since: 1.7.2
  */
@@ -343,13 +378,13 @@
   hb_font_t *font = hb_font_create (face);
   hb_face_destroy (face);
 
-  if (unlikely (hb_object_is_inert (font)))
+  if (unlikely (hb_object_is_immutable (font)))
     return font;
 
   hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
 
   /* Let there be dragons here... */
-  HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
+  font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
 
   return font;
 }
@@ -357,31 +392,8 @@
 CTFontRef
 hb_coretext_font_get_ct_font (hb_font_t *font)
 {
-  if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
-  return (CTFontRef) HB_SHAPER_DATA_GET (font);
-}
-
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_coretext_shaper_shape_plan_data_t {};
-
-hb_coretext_shaper_shape_plan_data_t *
-_hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                             const hb_feature_t *user_features HB_UNUSED,
-                                             unsigned int        num_user_features HB_UNUSED,
-                                             const int          *coords HB_UNUSED,
-                                             unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
-{
+  const hb_coretext_font_data_t *data = hb_coretext_font_data_sync (font);
+  return data ? (CTFontRef) data : nullptr;
 }
 
 
@@ -432,183 +444,6 @@
 };
 
 
-/* The following enum members are added in OS X 10.8. */
-#define kAltHalfWidthTextSelector               6
-#define kAltProportionalTextSelector            5
-#define kAlternateHorizKanaOffSelector          1
-#define kAlternateHorizKanaOnSelector           0
-#define kAlternateKanaType                      34
-#define kAlternateVertKanaOffSelector           3
-#define kAlternateVertKanaOnSelector            2
-#define kCaseSensitiveLayoutOffSelector         1
-#define kCaseSensitiveLayoutOnSelector          0
-#define kCaseSensitiveLayoutType                33
-#define kCaseSensitiveSpacingOffSelector        3
-#define kCaseSensitiveSpacingOnSelector         2
-#define kContextualAlternatesOffSelector        1
-#define kContextualAlternatesOnSelector         0
-#define kContextualAlternatesType               36
-#define kContextualLigaturesOffSelector         19
-#define kContextualLigaturesOnSelector          18
-#define kContextualSwashAlternatesOffSelector   5
-#define kContextualSwashAlternatesOnSelector    4
-#define kDefaultLowerCaseSelector               0
-#define kDefaultUpperCaseSelector               0
-#define kHistoricalLigaturesOffSelector         21
-#define kHistoricalLigaturesOnSelector          20
-#define kHojoCharactersSelector                 12
-#define kJIS2004CharactersSelector              11
-#define kLowerCasePetiteCapsSelector            2
-#define kLowerCaseSmallCapsSelector             1
-#define kLowerCaseType                          37
-#define kMathematicalGreekOffSelector           11
-#define kMathematicalGreekOnSelector            10
-#define kNLCCharactersSelector                  13
-#define kQuarterWidthTextSelector               4
-#define kScientificInferiorsSelector            4
-#define kStylisticAltEightOffSelector           17
-#define kStylisticAltEightOnSelector            16
-#define kStylisticAltEighteenOffSelector        37
-#define kStylisticAltEighteenOnSelector         36
-#define kStylisticAltElevenOffSelector          23
-#define kStylisticAltElevenOnSelector           22
-#define kStylisticAltFifteenOffSelector         31
-#define kStylisticAltFifteenOnSelector          30
-#define kStylisticAltFiveOffSelector            11
-#define kStylisticAltFiveOnSelector             10
-#define kStylisticAltFourOffSelector            9
-#define kStylisticAltFourOnSelector             8
-#define kStylisticAltFourteenOffSelector        29
-#define kStylisticAltFourteenOnSelector         28
-#define kStylisticAltNineOffSelector            19
-#define kStylisticAltNineOnSelector             18
-#define kStylisticAltNineteenOffSelector        39
-#define kStylisticAltNineteenOnSelector         38
-#define kStylisticAltOneOffSelector             3
-#define kStylisticAltOneOnSelector              2
-#define kStylisticAltSevenOffSelector           15
-#define kStylisticAltSevenOnSelector            14
-#define kStylisticAltSeventeenOffSelector       35
-#define kStylisticAltSeventeenOnSelector        34
-#define kStylisticAltSixOffSelector             13
-#define kStylisticAltSixOnSelector              12
-#define kStylisticAltSixteenOffSelector         33
-#define kStylisticAltSixteenOnSelector          32
-#define kStylisticAltTenOffSelector             21
-#define kStylisticAltTenOnSelector              20
-#define kStylisticAltThirteenOffSelector        27
-#define kStylisticAltThirteenOnSelector         26
-#define kStylisticAltThreeOffSelector           7
-#define kStylisticAltThreeOnSelector            6
-#define kStylisticAltTwelveOffSelector          25
-#define kStylisticAltTwelveOnSelector           24
-#define kStylisticAltTwentyOffSelector          41
-#define kStylisticAltTwentyOnSelector           40
-#define kStylisticAltTwoOffSelector             5
-#define kStylisticAltTwoOnSelector              4
-#define kStylisticAlternativesType              35
-#define kSwashAlternatesOffSelector             3
-#define kSwashAlternatesOnSelector              2
-#define kThirdWidthTextSelector                 3
-#define kTraditionalNamesCharactersSelector     14
-#define kUpperCasePetiteCapsSelector            2
-#define kUpperCaseSmallCapsSelector             1
-#define kUpperCaseType                          38
-
-/* Table data courtesy of Apple. */
-static const struct feature_mapping_t {
-    FourCharCode otFeatureTag;
-    uint16_t aatFeatureType;
-    uint16_t selectorToEnable;
-    uint16_t selectorToDisable;
-} feature_mappings[] = {
-    { 'c2pc',   kUpperCaseType,             kUpperCasePetiteCapsSelector,           kDefaultUpperCaseSelector },
-    { 'c2sc',   kUpperCaseType,             kUpperCaseSmallCapsSelector,            kDefaultUpperCaseSelector },
-    { 'calt',   kContextualAlternatesType,  kContextualAlternatesOnSelector,        kContextualAlternatesOffSelector },
-    { 'case',   kCaseSensitiveLayoutType,   kCaseSensitiveLayoutOnSelector,         kCaseSensitiveLayoutOffSelector },
-    { 'clig',   kLigaturesType,             kContextualLigaturesOnSelector,         kContextualLigaturesOffSelector },
-    { 'cpsp',   kCaseSensitiveLayoutType,   kCaseSensitiveSpacingOnSelector,        kCaseSensitiveSpacingOffSelector },
-    { 'cswh',   kContextualAlternatesType,  kContextualSwashAlternatesOnSelector,   kContextualSwashAlternatesOffSelector },
-    { 'dlig',   kLigaturesType,             kRareLigaturesOnSelector,               kRareLigaturesOffSelector },
-    { 'expt',   kCharacterShapeType,        kExpertCharactersSelector,              16 },
-    { 'frac',   kFractionsType,             kDiagonalFractionsSelector,             kNoFractionsSelector },
-    { 'fwid',   kTextSpacingType,           kMonospacedTextSelector,                7 },
-    { 'halt',   kTextSpacingType,           kAltHalfWidthTextSelector,              7 },
-    { 'hist',   kLigaturesType,             kHistoricalLigaturesOnSelector,         kHistoricalLigaturesOffSelector },
-    { 'hkna',   kAlternateKanaType,         kAlternateHorizKanaOnSelector,          kAlternateHorizKanaOffSelector, },
-    { 'hlig',   kLigaturesType,             kHistoricalLigaturesOnSelector,         kHistoricalLigaturesOffSelector },
-    { 'hngl',   kTransliterationType,       kHanjaToHangulSelector,                 kNoTransliterationSelector },
-    { 'hojo',   kCharacterShapeType,        kHojoCharactersSelector,                16 },
-    { 'hwid',   kTextSpacingType,           kHalfWidthTextSelector,                 7 },
-    { 'ital',   kItalicCJKRomanType,        kCJKItalicRomanOnSelector,              kCJKItalicRomanOffSelector },
-    { 'jp04',   kCharacterShapeType,        kJIS2004CharactersSelector,             16 },
-    { 'jp78',   kCharacterShapeType,        kJIS1978CharactersSelector,             16 },
-    { 'jp83',   kCharacterShapeType,        kJIS1983CharactersSelector,             16 },
-    { 'jp90',   kCharacterShapeType,        kJIS1990CharactersSelector,             16 },
-    { 'liga',   kLigaturesType,             kCommonLigaturesOnSelector,             kCommonLigaturesOffSelector },
-    { 'lnum',   kNumberCaseType,            kUpperCaseNumbersSelector,              2 },
-    { 'mgrk',   kMathematicalExtrasType,    kMathematicalGreekOnSelector,           kMathematicalGreekOffSelector },
-    { 'nlck',   kCharacterShapeType,        kNLCCharactersSelector,                 16 },
-    { 'onum',   kNumberCaseType,            kLowerCaseNumbersSelector,              2 },
-    { 'ordn',   kVerticalPositionType,      kOrdinalsSelector,                      kNormalPositionSelector },
-    { 'palt',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'pcap',   kLowerCaseType,             kLowerCasePetiteCapsSelector,           kDefaultLowerCaseSelector },
-    { 'pkna',   kTextSpacingType,           kProportionalTextSelector,              7 },
-    { 'pnum',   kNumberSpacingType,         kProportionalNumbersSelector,           4 },
-    { 'pwid',   kTextSpacingType,           kProportionalTextSelector,              7 },
-    { 'qwid',   kTextSpacingType,           kQuarterWidthTextSelector,              7 },
-    { 'ruby',   kRubyKanaType,              kRubyKanaOnSelector,                    kRubyKanaOffSelector },
-    { 'sinf',   kVerticalPositionType,      kScientificInferiorsSelector,           kNormalPositionSelector },
-    { 'smcp',   kLowerCaseType,             kLowerCaseSmallCapsSelector,            kDefaultLowerCaseSelector },
-    { 'smpl',   kCharacterShapeType,        kSimplifiedCharactersSelector,          16 },
-    { 'ss01',   kStylisticAlternativesType, kStylisticAltOneOnSelector,             kStylisticAltOneOffSelector },
-    { 'ss02',   kStylisticAlternativesType, kStylisticAltTwoOnSelector,             kStylisticAltTwoOffSelector },
-    { 'ss03',   kStylisticAlternativesType, kStylisticAltThreeOnSelector,           kStylisticAltThreeOffSelector },
-    { 'ss04',   kStylisticAlternativesType, kStylisticAltFourOnSelector,            kStylisticAltFourOffSelector },
-    { 'ss05',   kStylisticAlternativesType, kStylisticAltFiveOnSelector,            kStylisticAltFiveOffSelector },
-    { 'ss06',   kStylisticAlternativesType, kStylisticAltSixOnSelector,             kStylisticAltSixOffSelector },
-    { 'ss07',   kStylisticAlternativesType, kStylisticAltSevenOnSelector,           kStylisticAltSevenOffSelector },
-    { 'ss08',   kStylisticAlternativesType, kStylisticAltEightOnSelector,           kStylisticAltEightOffSelector },
-    { 'ss09',   kStylisticAlternativesType, kStylisticAltNineOnSelector,            kStylisticAltNineOffSelector },
-    { 'ss10',   kStylisticAlternativesType, kStylisticAltTenOnSelector,             kStylisticAltTenOffSelector },
-    { 'ss11',   kStylisticAlternativesType, kStylisticAltElevenOnSelector,          kStylisticAltElevenOffSelector },
-    { 'ss12',   kStylisticAlternativesType, kStylisticAltTwelveOnSelector,          kStylisticAltTwelveOffSelector },
-    { 'ss13',   kStylisticAlternativesType, kStylisticAltThirteenOnSelector,        kStylisticAltThirteenOffSelector },
-    { 'ss14',   kStylisticAlternativesType, kStylisticAltFourteenOnSelector,        kStylisticAltFourteenOffSelector },
-    { 'ss15',   kStylisticAlternativesType, kStylisticAltFifteenOnSelector,         kStylisticAltFifteenOffSelector },
-    { 'ss16',   kStylisticAlternativesType, kStylisticAltSixteenOnSelector,         kStylisticAltSixteenOffSelector },
-    { 'ss17',   kStylisticAlternativesType, kStylisticAltSeventeenOnSelector,       kStylisticAltSeventeenOffSelector },
-    { 'ss18',   kStylisticAlternativesType, kStylisticAltEighteenOnSelector,        kStylisticAltEighteenOffSelector },
-    { 'ss19',   kStylisticAlternativesType, kStylisticAltNineteenOnSelector,        kStylisticAltNineteenOffSelector },
-    { 'ss20',   kStylisticAlternativesType, kStylisticAltTwentyOnSelector,          kStylisticAltTwentyOffSelector },
-    { 'subs',   kVerticalPositionType,      kInferiorsSelector,                     kNormalPositionSelector },
-    { 'sups',   kVerticalPositionType,      kSuperiorsSelector,                     kNormalPositionSelector },
-    { 'swsh',   kContextualAlternatesType,  kSwashAlternatesOnSelector,             kSwashAlternatesOffSelector },
-    { 'titl',   kStyleOptionsType,          kTitlingCapsSelector,                   kNoStyleOptionsSelector },
-    { 'tnam',   kCharacterShapeType,        kTraditionalNamesCharactersSelector,    16 },
-    { 'tnum',   kNumberSpacingType,         kMonospacedNumbersSelector,             4 },
-    { 'trad',   kCharacterShapeType,        kTraditionalCharactersSelector,         16 },
-    { 'twid',   kTextSpacingType,           kThirdWidthTextSelector,                7 },
-    { 'unic',   kLetterCaseType,            14,                                     15 },
-    { 'valt',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'vert',   kVerticalSubstitutionType,  kSubstituteVerticalFormsOnSelector,     kSubstituteVerticalFormsOffSelector },
-    { 'vhal',   kTextSpacingType,           kAltHalfWidthTextSelector,              7 },
-    { 'vkna',   kAlternateKanaType,         kAlternateVertKanaOnSelector,           kAlternateVertKanaOffSelector },
-    { 'vpal',   kTextSpacingType,           kAltProportionalTextSelector,           7 },
-    { 'vrt2',   kVerticalSubstitutionType,  kSubstituteVerticalFormsOnSelector,     kSubstituteVerticalFormsOffSelector },
-    { 'zero',   kTypographicExtrasType,     kSlashedZeroOnSelector,                 kSlashedZeroOffSelector },
-};
-
-static int
-_hb_feature_mapping_cmp (const void *key_, const void *entry_)
-{
-  unsigned int key = * (unsigned int *) key_;
-  const feature_mapping_t * entry = (const feature_mapping_t *) entry_;
-  return key < entry->otFeatureTag ? -1 :
-         key > entry->otFeatureTag ? 1 :
-         0;
-}
-
 hb_bool_t
 _hb_coretext_shape (hb_shape_plan_t    *shape_plan,
                     hb_font_t          *font,
@@ -617,15 +452,15 @@
                     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
-  CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font);
+  CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
+  CTFontRef ct_font = (CTFontRef) hb_coretext_font_data_sync (font);
 
   CGFloat ct_font_size = CTFontGetSize (ct_font);
   CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
   CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
 
   /* Attach marks to their bases, to match the 'ot' shaper.
-   * Adapted from hb-ot-shape:hb_form_clusters().
+   * Adapted from a very old version of hb-ot-shape:hb_form_clusters().
    * Note that this only makes us be closer to the 'ot' shaper,
    * but by no means the same.  For example, if there's
    * B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
@@ -641,8 +476,8 @@
         buffer->merge_clusters (i - 1, i + 1);
   }
 
-  hb_auto_t<hb_vector_t<feature_record_t> > feature_records;
-  hb_auto_t<hb_vector_t<range_record_t> > range_records;
+  hb_vector_t<feature_record_t> feature_records;
+  hb_vector_t<range_record_t> range_records;
 
   /*
    * Set up features.
@@ -651,14 +486,10 @@
   if (num_features)
   {
     /* Sort features by start/end events. */
-    hb_auto_t<hb_vector_t<feature_event_t> > feature_events;
+    hb_vector_t<feature_event_t> feature_events;
     for (unsigned int i = 0; i < num_features; i++)
     {
-      const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag,
-                                                                               feature_mappings,
-                                                                               ARRAY_LENGTH (feature_mappings),
-                                                                               sizeof (feature_mappings[0]),
-                                                                               _hb_feature_mapping_cmp);
+      const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag);
       if (!mapping)
         continue;
 
@@ -694,9 +525,9 @@
     }
 
     /* Scan events and save features for each range. */
-    hb_auto_t<hb_vector_t<active_feature_t> > active_features;
+    hb_vector_t<active_feature_t> active_features;
     unsigned int last_index = 0;
-    for (unsigned int i = 0; i < feature_events.len; i++)
+    for (unsigned int i = 0; i < feature_events.length; i++)
     {
       feature_event_t *event = &feature_events[i];
 
@@ -705,13 +536,13 @@
         /* Save a snapshot of active features and the range. */
         range_record_t *range = range_records.push ();
 
-        if (active_features.len)
+        if (active_features.length)
         {
           CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
 
           /* TODO sort and resolve conflicting features? */
           /* active_features.qsort (); */
-          for (unsigned int j = 0; j < active_features.len; j++)
+          for (unsigned int j = 0; j < active_features.length; j++)
           {
             CFStringRef keys[] = {
               kCTFontFeatureTypeIdentifierKey,
@@ -767,7 +598,7 @@
       } else {
         active_feature_t *feature = active_features.find (&event->feature);
         if (feature)
-          active_features.remove (feature - active_features.arrayZ);
+          active_features.remove (feature - active_features.arrayZ ());
       }
     }
   }
@@ -824,7 +655,7 @@
   CFStringRef string_ref = nullptr;
   CTLineRef line = nullptr;
 
-  if (0)
+  if (false)
   {
 resize_and_retry:
     DEBUG_MSG (CORETEXT, buffer, "Buffer resize");
@@ -899,7 +730,7 @@
       CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
                                       kCTFontAttributeName, ct_font);
 
-      if (num_features && range_records.len)
+      if (num_features && range_records.length)
       {
         unsigned int start = 0;
         range_record_t *last_range = &range_records[0];
@@ -1048,7 +879,7 @@
          * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
          */
         bool matched = false;
-        for (unsigned int i = 0; i < range_records.len; i++)
+        for (unsigned int i = 0; i < range_records.length; i++)
           if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font))
           {
             matched = true;
@@ -1235,7 +1066,7 @@
      *
      * https://crbug.com/419769
      */
-    if (0)
+    if (false)
     {
       /* Make sure all runs had the expected direction. */
       bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
@@ -1311,7 +1142,7 @@
   if (line)
     CFRelease (line);
 
-  for (unsigned int i = 0; i < range_records.len; i++)
+  for (unsigned int i = 0; i < range_records.length; i++)
     if (range_records[i].font)
       CFRelease (range_records[i].font);
 
@@ -1323,36 +1154,21 @@
  * AAT shaper
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
-
 /*
  * shaper face data
  */
 
-struct hb_coretext_aat_shaper_face_data_t {};
+struct hb_coretext_aat_face_data_t {};
 
-hb_coretext_aat_shaper_face_data_t *
+hb_coretext_aat_face_data_t *
 _hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
 {
-  static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
-
-  for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++)
-  {
-    hb_blob_t *blob = face->reference_table (tags[i]);
-    if (hb_blob_get_length (blob))
-    {
-      hb_blob_destroy (blob);
-      return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
-    }
-    hb_blob_destroy (blob);
-  }
-
-  return nullptr;
+  return hb_aat_layout_has_substitution (face) || hb_aat_layout_has_positioning (face) ?
+         (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
 }
 
 void
-_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
 {
 }
 
@@ -1361,38 +1177,16 @@
  * shaper font data
  */
 
-struct hb_coretext_aat_shaper_font_data_t {};
+struct hb_coretext_aat_font_data_t {};
 
-hb_coretext_aat_shaper_font_data_t *
+hb_coretext_aat_font_data_t *
 _hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
 {
-  return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
+  return font->data.coretext ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
 }
 
 void
-_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_coretext_aat_shaper_shape_plan_data_t {};
-
-hb_coretext_aat_shaper_shape_plan_data_t *
-_hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                             const hb_feature_t *user_features HB_UNUSED,
-                                             unsigned int        num_user_features HB_UNUSED,
-                                             const int          *coords HB_UNUSED,
-                                             unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
 {
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-debug.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-debug.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,13 +27,60 @@
 #ifndef HB_DEBUG_HH
 #define HB_DEBUG_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
+#include "hb-atomic.hh"
+#include "hb-dsalgs.hh"
 
 
 #ifndef HB_DEBUG
 #define HB_DEBUG 0
 #endif
 
+
+/*
+ * Global runtime options.
+ */
+
+struct hb_options_t
+{
+  bool unused : 1; /* In-case sign bit is here. */
+  bool initialized : 1;
+  bool uniscribe_bug_compatible : 1;
+  bool aat : 1;
+};
+
+union hb_options_union_t {
+  int i;
+  hb_options_t opts;
+};
+static_assert ((sizeof (hb_atomic_int_t) >= sizeof (hb_options_union_t)), "");
+
+HB_INTERNAL void
+_hb_options_init ();
+
+extern HB_INTERNAL hb_atomic_int_t _hb_options;
+
+static inline hb_options_t
+hb_options ()
+{
+  /* Make a local copy, so we can access bitfield threadsafely. */
+  hb_options_union_t u;
+  u.i = _hb_options.get_relaxed ();
+
+  if (unlikely (!u.i))
+  {
+    _hb_options_init ();
+    u.i = _hb_options.get_relaxed ();
+  }
+
+  return u.opts;
+}
+
+
+/*
+ * Debug output (needs enabling at compile time.)
+ */
+
 static inline bool
 _hb_debug (unsigned int level,
            unsigned int max_level)
@@ -126,7 +173,7 @@
 
   fprintf (stderr, "\n");
 }
-template <> inline void
+template <> inline void HB_PRINTF_FUNC(7, 0)
 _hb_debug_msg_va<0> (const char *what HB_UNUSED,
                      const void *obj HB_UNUSED,
                      const char *func HB_UNUSED,
@@ -145,7 +192,7 @@
                int level_dir,
                const char *message,
                ...) HB_PRINTF_FUNC(7, 8);
-template <int max_level> static inline void
+template <int max_level> static inline void HB_PRINTF_FUNC(7, 8)
 _hb_debug_msg (const char *what,
                const void *obj,
                const char *func,
@@ -169,7 +216,7 @@
                   int level_dir HB_UNUSED,
                   const char *message HB_UNUSED,
                   ...) HB_PRINTF_FUNC(7, 8);
-template <> inline void
+template <> inline void HB_PRINTF_FUNC(7, 8)
 _hb_debug_msg<0> (const char *what HB_UNUSED,
                   const void *obj HB_UNUSED,
                   const char *func HB_UNUSED,
@@ -237,7 +284,7 @@
     _hb_debug_msg_va<max_level> (what, obj, func, true, plevel ? *plevel : 0, +1, message, ap);
     va_end (ap);
   }
-  inline ~hb_auto_trace_t (void)
+  ~hb_auto_trace_t ()
   {
     _hb_warn_no_return<ret_t> (returned);
     if (!returned) {
@@ -246,14 +293,16 @@
     if (plevel) --*plevel;
   }
 
-  inline ret_t ret (ret_t v, unsigned int line = 0)
+  ret_t ret (ret_t v,
+             const char *func = "",
+             unsigned int line = 0)
   {
     if (unlikely (returned)) {
       fprintf (stderr, "OUCH, double calls to return_trace().  This is a bug, please report.\n");
       return v;
     }
 
-    _hb_debug_msg<max_level> (what, obj, nullptr, true, plevel ? *plevel : 1, -1,
+    _hb_debug_msg<max_level> (what, obj, func, true, plevel ? *plevel : 1, -1,
                               "return %s (line %d)",
                               hb_printer_t<ret_t>().print (v), line);
     if (plevel) --*plevel;
@@ -278,17 +327,21 @@
                                    const char *message,
                                    ...) HB_PRINTF_FUNC(6, 7) {}
 
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
+  ret_t ret (ret_t v,
+             const char *func HB_UNUSED = nullptr,
+             unsigned int line HB_UNUSED = 0) { return v; }
 };
 
 /* For disabled tracing; optimize out everything.
  * https://github.com/harfbuzz/harfbuzz/pull/605 */
 template <typename ret_t>
 struct hb_no_trace_t {
-  inline ret_t ret (ret_t v, unsigned int line HB_UNUSED = 0) { return v; }
+  ret_t ret (ret_t v,
+             const char *func HB_UNUSED = "",
+             unsigned int line HB_UNUSED = 0) { return v; }
 };
 
-#define return_trace(RET) return trace.ret (RET, __LINE__)
+#define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
 
 
 /*
@@ -348,30 +401,6 @@
 #define TRACE_APPLY(this) hb_no_trace_t<bool> trace
 #endif
 
-#ifndef HB_DEBUG_CLOSURE
-#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_CLOSURE
-#define TRACE_CLOSURE(this) \
-        hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
-        (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-         " ")
-#else
-#define TRACE_CLOSURE(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
-#endif
-
-#ifndef HB_DEBUG_COLLECT_GLYPHS
-#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
-#endif
-#if HB_DEBUG_COLLECT_GLYPHS
-#define TRACE_COLLECT_GLYPHS(this) \
-        hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
-        (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-         " ")
-#else
-#define TRACE_COLLECT_GLYPHS(this) hb_no_trace_t<hb_void_t> trace HB_UNUSED
-#endif
-
 #ifndef HB_DEBUG_SANITIZE
 #define HB_DEBUG_SANITIZE (HB_DEBUG+0)
 #endif
@@ -423,8 +452,6 @@
 #ifndef HB_DEBUG_DISPATCH
 #define HB_DEBUG_DISPATCH ( \
         HB_DEBUG_APPLY + \
-        HB_DEBUG_CLOSURE + \
-        HB_DEBUG_COLLECT_GLYPHS + \
         HB_DEBUG_SANITIZE + \
         HB_DEBUG_SERIALIZE + \
   HB_DEBUG_SUBSET + \
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-deprecated.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-deprecated.h	Tue Mar 26 09:05:10 2019 -0400
@@ -36,10 +36,23 @@
 #include "hb-font.h"
 #include "hb-set.h"
 
+
+/**
+ * SECTION:hb-deprecated
+ * @title: hb-deprecated
+ * @short_description: Deprecated API
+ * @include: hb.h
+ *
+ * These API have been deprecated in favor of newer API, or because they
+ * were deemed unnecessary.
+ **/
+
+
 HB_BEGIN_DECLS
 
 #ifndef HB_DISABLE_DEPRECATED
 
+
 #define HB_SCRIPT_CANADIAN_ABORIGINAL           HB_SCRIPT_CANADIAN_SYLLABICS
 
 #define HB_BUFFER_FLAGS_DEFAULT                 HB_BUFFER_FLAG_DEFAULT
@@ -50,13 +63,161 @@
                                                hb_codepoint_t *glyph,
                                                void *user_data);
 
-HB_EXTERN void
+HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func or hb_font_funcs_set_variation_glyph_func) void
 hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
                               hb_font_get_glyph_func_t func,
                               void *user_data, hb_destroy_func_t destroy);
 
+HB_EXTERN HB_DEPRECATED void
+hb_set_invert (hb_set_t *set);
+
+/**
+ * hb_unicode_eastasian_width_func_t:
+ *
+ * Deprecated: 2.0.0
+ */
+typedef unsigned int                    (*hb_unicode_eastasian_width_func_t)    (hb_unicode_funcs_t *ufuncs,
+                                                                                 hb_codepoint_t      unicode,
+                                                                                 void               *user_data);
+
+/**
+ * hb_unicode_funcs_set_eastasian_width_func:
+ * @ufuncs: a Unicode function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED void
+hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
+                                           hb_unicode_eastasian_width_func_t func,
+                                           void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_unicode_eastasian_width:
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED unsigned int
+hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
+                            hb_codepoint_t unicode);
+
+
+/**
+ * hb_unicode_decompose_compatibility_func_t:
+ * @ufuncs: a Unicode function structure
+ * @u: codepoint to decompose
+ * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
+ * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
+ *
+ * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
+ * The complete length of the decomposition will be returned.
+ *
+ * If @u has no compatibility decomposition, zero should be returned.
+ *
+ * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
+ * compatibility decomposition plus an terminating value of 0.  Consequently, @decompose must be allocated by the caller to be at least this length.  Implementations
+ * of this function type must ensure that they do not write past the provided array.
+ *
+ * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available.
+ *
+ * Deprecated: 2.0.0
+ */
+typedef unsigned int                    (*hb_unicode_decompose_compatibility_func_t)    (hb_unicode_funcs_t *ufuncs,
+                                                                                         hb_codepoint_t      u,
+                                                                                         hb_codepoint_t     *decomposed,
+                                                                                         void               *user_data);
+
+/**
+ * HB_UNICODE_MAX_DECOMPOSITION_LEN:
+ *
+ * See Unicode 6.1 for details on the maximum decomposition length.
+ *
+ * Deprecated: 2.0.0
+ */
+#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
+
+/**
+ * hb_unicode_funcs_set_decompose_compatibility_func:
+ * @ufuncs: a Unicode function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN HB_DEPRECATED void
+hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
+                                                   hb_unicode_decompose_compatibility_func_t func,
+                                                   void *user_data, hb_destroy_func_t destroy);
+
+HB_EXTERN HB_DEPRECATED unsigned int
+hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
+                                    hb_codepoint_t      u,
+                                    hb_codepoint_t     *decomposed);
+
+
+typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
+                                                           hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                                           void *user_data);
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
+
+/**
+ * hb_font_funcs_set_glyph_h_kerning_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
 HB_EXTERN void
-hb_set_invert (hb_set_t *set);
+hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
+                                        hb_font_get_glyph_h_kerning_func_t func,
+                                        void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_glyph_v_kerning_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 0.9.2
+ * Deprecated: 2.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
+                                        hb_font_get_glyph_v_kerning_func_t func,
+                                        void *user_data, hb_destroy_func_t destroy);
+
+HB_EXTERN hb_position_t
+hb_font_get_glyph_h_kerning (hb_font_t *font,
+                             hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
+HB_EXTERN hb_position_t
+hb_font_get_glyph_v_kerning (hb_font_t *font,
+                             hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
+
+HB_EXTERN void
+hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
+                                         hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                         hb_direction_t direction,
+                                         hb_position_t *x, hb_position_t *y);
+
 
 #endif
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-dsalgs.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-dsalgs.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,8 +27,338 @@
 #ifndef HB_DSALGS_HH
 #define HB_DSALGS_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
+#include "hb-null.hh"
+
+
+/* Void! For when we need a expression-type of void. */
+typedef const struct _hb_void_t *hb_void_t;
+#define HB_VOID ((const _hb_void_t *) nullptr)
+
+
+/*
+ * Bithacks.
+ */
+
+/* Return the number of 1 bits in v. */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_popcount (T v)
+{
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return __builtin_popcount (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return __builtin_popcountl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return __builtin_popcountll (v);
+#endif
+
+  if (sizeof (T) <= 4)
+  {
+    /* "HACKMEM 169" */
+    uint32_t y;
+    y = (v >> 1) &033333333333;
+    y = v - y - ((y >>1) & 033333333333);
+    return (((y + (y >> 3)) & 030707070707) % 077);
+  }
+
+  if (sizeof (T) == 8)
+  {
+    unsigned int shift = 32;
+    return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
+  }
+
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+/* Returns the number of bits needed to store number */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_bit_storage (T v)
+{
+  if (unlikely (!v)) return 0;
+
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return sizeof (unsigned int) * 8 - __builtin_clz (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+  if (sizeof (T) <= sizeof (unsigned int))
+  {
+    unsigned long where;
+    _BitScanReverse (&where, v);
+    return 1 + where;
+  }
+# if defined(_WIN64)
+  if (sizeof (T) <= 8)
+  {
+    unsigned long where;
+    _BitScanReverse64 (&where, v);
+    return 1 + where;
+  }
+# endif
+#endif
+
+  if (sizeof (T) <= 4)
+  {
+    /* "bithacks" */
+    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+    const unsigned int S[] = {1, 2, 4, 8, 16};
+    unsigned int r = 0;
+    for (int i = 4; i >= 0; i--)
+      if (v & b[i])
+      {
+        v >>= S[i];
+        r |= S[i];
+      }
+    return r + 1;
+  }
+  if (sizeof (T) <= 8)
+  {
+    /* "bithacks" */
+    const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
+    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
+    unsigned int r = 0;
+    for (int i = 5; i >= 0; i--)
+      if (v & b[i])
+      {
+        v >>= S[i];
+        r |= S[i];
+      }
+    return r + 1;
+  }
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
+                          hb_bit_storage<uint64_t> ((uint64_t) v);
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+/* Returns the number of zero bits in the least significant side of v */
+template <typename T>
+static inline HB_CONST_FUNC unsigned int
+hb_ctz (T v)
+{
+  if (unlikely (!v)) return 0;
+
+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
+  if (sizeof (T) <= sizeof (unsigned int))
+    return __builtin_ctz (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return __builtin_ctzl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return __builtin_ctzll (v);
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+  if (sizeof (T) <= sizeof (unsigned int))
+  {
+    unsigned long where;
+    _BitScanForward (&where, v);
+    return where;
+  }
+# if defined(_WIN64)
+  if (sizeof (T) <= 8)
+  {
+    unsigned long where;
+    _BitScanForward64 (&where, v);
+    return where;
+  }
+# endif
+#endif
 
+  if (sizeof (T) <= 4)
+  {
+    /* "bithacks" */
+    unsigned int c = 32;
+    v &= - (int32_t) v;
+    if (v) c--;
+    if (v & 0x0000FFFF) c -= 16;
+    if (v & 0x00FF00FF) c -= 8;
+    if (v & 0x0F0F0F0F) c -= 4;
+    if (v & 0x33333333) c -= 2;
+    if (v & 0x55555555) c -= 1;
+    return c;
+  }
+  if (sizeof (T) <= 8)
+  {
+    /* "bithacks" */
+    unsigned int c = 64;
+    v &= - (int64_t) (v);
+    if (v) c--;
+    if (v & 0x00000000FFFFFFFFULL) c -= 32;
+    if (v & 0x0000FFFF0000FFFFULL) c -= 16;
+    if (v & 0x00FF00FF00FF00FFULL) c -= 8;
+    if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
+    if (v & 0x3333333333333333ULL) c -= 2;
+    if (v & 0x5555555555555555ULL) c -= 1;
+    return c;
+  }
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
+                          hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
+  }
+
+  assert (0);
+  return 0; /* Shut up stupid compiler. */
+}
+
+
+/*
+ * Tiny stuff.
+ */
+
+template <typename T>
+static inline T* hb_addressof (T& arg)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  /* https://en.cppreference.com/w/cpp/memory/addressof */
+  return reinterpret_cast<T*>(
+           &const_cast<char&>(
+              reinterpret_cast<const volatile char&>(arg)));
+#pragma GCC diagnostic pop
+}
+
+/* ASCII tag/character handling */
+static inline bool ISALPHA (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
+static inline bool ISALNUM (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
+static inline bool ISSPACE (unsigned char c)
+{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
+static inline unsigned char TOUPPER (unsigned char c)
+{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
+static inline unsigned char TOLOWER (unsigned char c)
+{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
+
+#undef MIN
+template <typename Type>
+static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
+
+#undef MAX
+template <typename Type>
+static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
+
+static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
+{ return (a + (b - 1)) / b; }
+
+
+#undef  ARRAY_LENGTH
+template <typename Type, unsigned int n>
+static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
+/* A const version, but does not detect erratically being called on pointers. */
+#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
+
+
+static inline int
+hb_memcmp (const void *a, const void *b, unsigned int len)
+{
+  /* It's illegal to pass NULL to memcmp(), even if len is zero.
+   * So, wrap it.
+   * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
+  if (!len) return 0;
+  return memcmp (a, b, len);
+}
+
+static inline bool
+hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
+{
+  return (size > 0) && (count >= ((unsigned int) -1) / size);
+}
+
+static inline unsigned int
+hb_ceil_to_4 (unsigned int v)
+{
+  return ((v - 1) | 3) + 1;
+}
+
+template <typename T> struct hb_is_signed;
+/* https://github.com/harfbuzz/harfbuzz/issues/1535 */
+template <> struct hb_is_signed<int8_t> { enum { value = true }; };
+template <> struct hb_is_signed<int16_t> { enum { value = true }; };
+template <> struct hb_is_signed<int32_t> { enum { value = true }; };
+template <> struct hb_is_signed<int64_t> { enum { value = true }; };
+template <> struct hb_is_signed<uint8_t> { enum { value = false }; };
+template <> struct hb_is_signed<uint16_t> { enum { value = false }; };
+template <> struct hb_is_signed<uint32_t> { enum { value = false }; };
+template <> struct hb_is_signed<uint64_t> { enum { value = false }; };
+
+template <typename T> static inline bool
+hb_in_range (T u, T lo, T hi)
+{
+  /* The sizeof() is here to force template instantiation.
+   * I'm sure there are better ways to do this but can't think of
+   * one right now.  Declaring a variable won't work as HB_UNUSED
+   * is unusable on some platforms and unused types are less likely
+   * to generate a warning than unused variables. */
+  static_assert (!hb_is_signed<T>::value, "");
+
+  /* The casts below are important as if T is smaller than int,
+   * the subtract results will become a signed int! */
+  return (T)(u - lo) <= (T)(hi - lo);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
+{
+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
+{
+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
+}
+
+
+/*
+ * Sort and search.
+ */
+
+static inline void *
+hb_bsearch (const void *key, const void *base,
+            size_t nmemb, size_t size,
+            int (*compar)(const void *_key, const void *_item))
+{
+  int min = 0, max = (int) nmemb - 1;
+  while (min <= max)
+  {
+    int mid = (min + max) / 2;
+    const void *p = (const void *) (((const char *) base) + (mid * size));
+    int c = compar (key, p);
+    if (c < 0)
+      max = mid - 1;
+    else if (c > 0)
+      min = mid + 1;
+    else
+      return (void *) p;
+  }
+  return nullptr;
+}
 
 static inline void *
 hb_bsearch_r (const void *key, const void *base,
@@ -39,7 +369,7 @@
   int min = 0, max = (int) nmemb - 1;
   while (min <= max)
   {
-    int mid = (min + max) / 2;
+    int mid = ((unsigned int) min + (unsigned int) max) / 2;
     const void *p = (const void *) (((const char *) base) + (mid * size));
     int c = compar (key, p, arg);
     if (c < 0)
@@ -53,8 +383,12 @@
 }
 
 
-
-/* From https://github.com/noporpoise/sort_r */
+/* From https://github.com/noporpoise/sort_r
+ * With following modifications:
+ *
+ * 10 November 2018:
+ * https://github.com/noporpoise/sort_r/issues/7
+ */
 
 /* Isaac Turner 29 April 2014 Public Domain */
 
@@ -110,7 +444,7 @@
 
     /* Use median of first, middle and last items as pivot */
     char *x, *y, *xend, ch;
-    char *pl, *pr;
+    char *pl, *pm, *pr;
     char *last = b+w*(nel-1), *tmp;
     char *l[3];
     l[0] = b;
@@ -132,13 +466,15 @@
     pr = last;
 
     while(pl < pr) {
-      for(; pl < pr; pl += w) {
+      pm = pl+((pr-pl+1)>>1);
+      for(; pl < pm; pl += w) {
         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
           pr -= w; /* pivot now at pl */
           break;
         }
       }
-      for(; pl < pr; pr -= w) {
+      pm = pl+((pr-pl)>>1);
+      for(; pm < pr; pr -= w) {
         if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
           pl += w; /* pivot now at pr */
           break;
@@ -158,4 +494,139 @@
     sort_r_simple(base, nel, width, compar, arg);
 }
 
+
+template <typename T, typename T2> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
+{
+  for (unsigned int i = 1; i < len; i++)
+  {
+    unsigned int j = i;
+    while (j && compar (&array[j - 1], &array[i]) > 0)
+      j--;
+    if (i == j)
+      continue;
+    /* Move item i to occupy place for item j, shift what's in between. */
+    {
+      T t = array[i];
+      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
+      array[j] = t;
+    }
+    if (array2)
+    {
+      T2 t = array2[i];
+      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
+      array2[j] = t;
+    }
+  }
+}
+
+template <typename T> static inline void
+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
+{
+  hb_stable_sort (array, len, compar, (int *) nullptr);
+}
+
+static inline hb_bool_t
+hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
+{
+  /* Pain because we don't know whether s is nul-terminated. */
+  char buf[64];
+  len = MIN (ARRAY_LENGTH (buf) - 1, len);
+  strncpy (buf, s, len);
+  buf[len] = '\0';
+
+  char *end;
+  errno = 0;
+  unsigned long v = strtoul (buf, &end, base);
+  if (errno) return false;
+  if (*end) return false;
+  *out = v;
+  return true;
+}
+
+
+struct HbOpOr
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = true;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
+};
+struct HbOpAnd
+{
+  static constexpr bool passthru_left = false;
+  static constexpr bool passthru_right = false;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
+};
+struct HbOpMinus
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = false;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
+};
+struct HbOpXor
+{
+  static constexpr bool passthru_left = true;
+  static constexpr bool passthru_right = true;
+  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
+};
+
+
+/* Compiler-assisted vectorization. */
+
+/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
+ * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
+ * Define that to 0 to disable. */
+template <typename elt_t, unsigned int byte_size>
+struct hb_vector_size_t
+{
+  elt_t& operator [] (unsigned int i) { return u.v[i]; }
+  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
+
+  void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
+
+  template <class Op>
+  hb_vector_size_t process (const hb_vector_size_t &o) const
+  {
+    hb_vector_size_t r;
+#if HB_VECTOR_SIZE
+    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
+        Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
+    else
+#endif
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
+        Op::process (r.u.v[i], u.v[i], o.u.v[i]);
+    return r;
+  }
+  hb_vector_size_t operator | (const hb_vector_size_t &o) const
+  { return process<HbOpOr> (o); }
+  hb_vector_size_t operator & (const hb_vector_size_t &o) const
+  { return process<HbOpAnd> (o); }
+  hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
+  { return process<HbOpXor> (o); }
+  hb_vector_size_t operator ~ () const
+  {
+    hb_vector_size_t r;
+#if HB_VECTOR_SIZE && 0
+    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
+        r.u.vec[i] = ~u.vec[i];
+    else
+#endif
+    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
+      r.u.v[i] = ~u.v[i];
+    return r;
+  }
+
+  private:
+  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
+  union {
+    elt_t v[byte_size / sizeof (elt_t)];
+#if HB_VECTOR_SIZE
+    hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
+#endif
+  } u;
+};
+
+
 #endif /* HB_DSALGS_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_FACE_PRIVATE_HH
-#define HB_FACE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-
-
-/*
- * hb_face_t
- */
-
-struct hb_face_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  hb_reference_table_func_t  reference_table_func;
-  void                      *user_data;
-  hb_destroy_func_t          destroy;
-
-  unsigned int index;                   /* Face index in a collection, zero-based. */
-  mutable unsigned int upem;            /* Units-per-EM. */
-  mutable unsigned int num_glyphs;      /* Number of glyphs. */
-
-  struct hb_shaper_data_t shaper_data;  /* Various shaper data. */
-
-  /* Various non-shaping data. */
-  /* ... */
-
-  /* Cache */
-  struct plan_node_t {
-    hb_shape_plan_t *shape_plan;
-    plan_node_t *next;
-  } *shape_plans;
-
-
-  inline hb_blob_t *reference_table (hb_tag_t tag) const
-  {
-    hb_blob_t *blob;
-
-    if (unlikely (!reference_table_func))
-      return hb_blob_get_empty ();
-
-    blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
-    if (unlikely (!blob))
-      return hb_blob_get_empty ();
-
-    return blob;
-  }
-
-  inline HB_PURE_FUNC unsigned int get_upem (void) const
-  {
-    if (unlikely (!upem))
-      load_upem ();
-    return upem;
-  }
-
-  inline unsigned int get_num_glyphs (void) const
-  {
-    if (unlikely (num_glyphs == (unsigned int) -1))
-      load_num_glyphs ();
-    return num_glyphs;
-  }
-
-  private:
-  HB_INTERNAL void load_upem (void) const;
-  HB_INTERNAL void load_num_glyphs (void) const;
-};
-
-extern HB_INTERNAL const hb_face_t _hb_face_nil;
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_FACE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,23 +26,35 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-face-private.hh"
-#include "hb-blob-private.hh"
-#include "hb-open-file-private.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-maxp-table.hh"
-
+#include "hb-face.hh"
+#include "hb-blob.hh"
+#include "hb-open-file.hh"
+#include "hb-ot-face.hh"
+#include "hb-ot-cmap-table.hh"
 
 
 /**
- * hb_face_count: Get number of faces on the blob
- * @blob:
+ * SECTION:hb-face
+ * @title: hb-face
+ * @short_description: Font face objects
+ * @include: hb.h
  *
- *
+ * Font face is objects represent a single face in a font family.
+ * More exactly, a font face represents a single face in a binary font file.
+ * Font faces are typically built from a binary blob and a face index.
+ * Font faces are used to create fonts.
+ **/
+
+
+/**
+ * hb_face_count:
+ * @blob: a blob.
  *
- * Return value: Number of faces on the blob
+ * Get number of faces in a blob.
+ *
+ * Return value: Number of faces in @blob
  *
  * Since: 1.7.7
  **/
@@ -52,36 +64,33 @@
   if (unlikely (!blob))
     return 0;
 
-  hb_blob_t *sanitized = OT::Sanitizer<OT::OpenTypeFontFile> ().sanitize (blob);
+  /* TODO We shouldn't be sanitizing blob.  Port to run sanitizer and return if not sane. */
+  /* Make API signature const after. */
+  hb_blob_t *sanitized = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob));
   const OT::OpenTypeFontFile& ot = *sanitized->as<OT::OpenTypeFontFile> ();
+  unsigned int ret = ot.get_face_count ();
+  hb_blob_destroy (sanitized);
 
-  return ot.get_face_count ();
+  return ret;
 }
 
 /*
  * hb_face_t
  */
 
-const hb_face_t _hb_face_nil = {
+DEFINE_NULL_INSTANCE (hb_face_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
-
   nullptr, /* reference_table_func */
   nullptr, /* user_data */
   nullptr, /* destroy */
 
   0,    /* index */
-  1000, /* upem */
-  0,    /* num_glyphs */
+  HB_ATOMIC_INT_INIT (1000), /* upem */
+  HB_ATOMIC_INT_INIT (0),    /* num_glyphs */
 
-  {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  },
-
-  nullptr, /* shape_plans */
+  /* Zero for the rest is fine. */
 };
 
 
@@ -114,8 +123,10 @@
   face->user_data = user_data;
   face->destroy = destroy;
 
-  face->upem = 0;
-  face->num_glyphs = (unsigned int) -1;
+  face->num_glyphs.set_relaxed (-1);
+
+  face->data.init0 (face);
+  face->table.init0 (face);
 
   return face;
 }
@@ -159,11 +170,12 @@
     return hb_blob_reference (data->blob);
 
   const OT::OpenTypeFontFile &ot_file = *data->blob->as<OT::OpenTypeFontFile> ();
-  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
+  unsigned int base_offset;
+  const OT::OpenTypeFontFace &ot_face = ot_file.get_face (data->index, &base_offset);
 
   const OT::OpenTypeTable &table = ot_face.get_table_by_tag (tag);
 
-  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
+  hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, base_offset + table.offset, table.length);
 
   return blob;
 }
@@ -188,7 +200,7 @@
   if (unlikely (!blob))
     blob = hb_blob_get_empty ();
 
-  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (hb_blob_reference (blob)), index);
+  hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (hb_blob_reference (blob)), index);
 
   if (unlikely (!closure))
     return hb_face_get_empty ();
@@ -212,9 +224,9 @@
  * Since: 0.9.2
  **/
 hb_face_t *
-hb_face_get_empty (void)
+hb_face_get_empty ()
 {
-  return const_cast<hb_face_t *> (&_hb_face_nil);
+  return const_cast<hb_face_t *> (&Null(hb_face_t));
 }
 
 
@@ -255,9 +267,8 @@
     node = next;
   }
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  face->data.fini ();
+  face->table.fini ();
 
   if (face->destroy)
     face->destroy (face->user_data);
@@ -301,7 +312,7 @@
  * Since: 0.9.2
  **/
 void *
-hb_face_get_user_data (hb_face_t          *face,
+hb_face_get_user_data (const hb_face_t    *face,
                        hb_user_data_key_t *key)
 {
   return hb_object_get_user_data (face, key);
@@ -318,10 +329,10 @@
 void
 hb_face_make_immutable (hb_face_t *face)
 {
-  if (unlikely (hb_object_is_inert (face)))
+  if (hb_object_is_immutable (face))
     return;
 
-  face->immutable = true;
+  hb_object_make_immutable (face);
 }
 
 /**
@@ -335,9 +346,9 @@
  * Since: 0.9.2
  **/
 hb_bool_t
-hb_face_is_immutable (hb_face_t *face)
+hb_face_is_immutable (const hb_face_t *face)
 {
-  return face->immutable;
+  return hb_object_is_immutable (face);
 }
 
 
@@ -353,8 +364,8 @@
  * Since: 0.9.2
  **/
 hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
-                         hb_tag_t   tag)
+hb_face_reference_table (const hb_face_t *face,
+                         hb_tag_t tag)
 {
   return face->reference_table (tag);
 }
@@ -388,7 +399,7 @@
 hb_face_set_index (hb_face_t    *face,
                    unsigned int  index)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
   face->index = index;
@@ -405,7 +416,7 @@
  * Since: 0.9.2
  **/
 unsigned int
-hb_face_get_index (hb_face_t    *face)
+hb_face_get_index (const hb_face_t *face)
 {
   return face->index;
 }
@@ -423,10 +434,10 @@
 hb_face_set_upem (hb_face_t    *face,
                   unsigned int  upem)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
-  face->upem = upem;
+  face->upem.set_relaxed (upem);
 }
 
 /**
@@ -440,20 +451,11 @@
  * Since: 0.9.2
  **/
 unsigned int
-hb_face_get_upem (hb_face_t *face)
+hb_face_get_upem (const hb_face_t *face)
 {
   return face->get_upem ();
 }
 
-void
-hb_face_t::load_upem (void) const
-{
-  hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (reference_table (HB_OT_TAG_head));
-  const OT::head *head_table = head_blob->as<OT::head> ();
-  upem = head_table->get_upem ();
-  hb_blob_destroy (head_blob);
-}
-
 /**
  * hb_face_set_glyph_count:
  * @face: a face.
@@ -467,10 +469,10 @@
 hb_face_set_glyph_count (hb_face_t    *face,
                          unsigned int  glyph_count)
 {
-  if (face->immutable)
+  if (hb_object_is_immutable (face))
     return;
 
-  face->num_glyphs = glyph_count;
+  face->num_glyphs.set_relaxed (glyph_count);
 }
 
 /**
@@ -484,23 +486,17 @@
  * Since: 0.9.7
  **/
 unsigned int
-hb_face_get_glyph_count (hb_face_t *face)
+hb_face_get_glyph_count (const hb_face_t *face)
 {
   return face->get_num_glyphs ();
 }
 
-void
-hb_face_t::load_num_glyphs (void) const
-{
-  hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (reference_table (HB_OT_TAG_maxp));
-  const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
-  num_glyphs = maxp_table->get_num_glyphs ();
-  hb_blob_destroy (maxp_blob);
-}
-
 /**
  * hb_face_get_table_tags:
  * @face: a face.
+ * @start_offset: index of first tag to return.
+ * @table_count: input length of @table_tags array, output number of items written.
+ * @table_tags: array to write tags into.
  *
  * Retrieves table tags for a face, if possible.
  *
@@ -509,7 +505,7 @@
  * Since: 1.6.0
  **/
 unsigned int
-hb_face_get_table_tags (hb_face_t    *face,
+hb_face_get_table_tags (const hb_face_t *face,
                         unsigned int  start_offset,
                         unsigned int *table_count, /* IN/OUT */
                         hb_tag_t     *table_tags /* OUT */)
@@ -528,3 +524,200 @@
 
   return ot_face.get_table_tags (start_offset, table_count, table_tags);
 }
+
+
+/*
+ * Character set.
+ */
+
+
+/**
+ * hb_face_collect_unicodes:
+ * @face: font face.
+ * @out: set to add Unicode characters covered by @face to.
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_unicodes (hb_face_t *face,
+                          hb_set_t  *out)
+{
+  face->table.cmap->collect_unicodes (out);
+}
+
+/**
+ * hb_face_collect_variation_selectors:
+ * @face: font face.
+ * @out: set to add Variation Selector characters covered by @face to.
+ *
+ *
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_variation_selectors (hb_face_t *face,
+                                     hb_set_t  *out)
+{
+  face->table.cmap->collect_variation_selectors (out);
+}
+
+/**
+ * hb_face_collect_variation_unicodes:
+ * @face: font face.
+ * @out: set to add Unicode characters for @variation_selector covered by @face to.
+ *
+ *
+ *
+ * Since: 1.9.0
+ */
+void
+hb_face_collect_variation_unicodes (hb_face_t *face,
+                                    hb_codepoint_t variation_selector,
+                                    hb_set_t  *out)
+{
+  face->table.cmap->collect_variation_unicodes (variation_selector, out);
+}
+
+
+
+/*
+ * face-builder: A face that has add_table().
+ */
+
+struct hb_face_builder_data_t
+{
+  struct table_entry_t
+  {
+    int cmp (hb_tag_t t) const
+    {
+      if (t < tag) return -1;
+      if (t > tag) return -1;
+      return 0;
+    }
+
+    hb_tag_t   tag;
+    hb_blob_t *blob;
+  };
+
+  hb_vector_t<table_entry_t> tables;
+};
+
+static hb_face_builder_data_t *
+_hb_face_builder_data_create ()
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) calloc (1, sizeof (hb_face_builder_data_t));
+  if (unlikely (!data))
+    return nullptr;
+
+  data->tables.init ();
+
+  return data;
+}
+
+static void
+_hb_face_builder_data_destroy (void *user_data)
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+  for (unsigned int i = 0; i < data->tables.length; i++)
+    hb_blob_destroy (data->tables[i].blob);
+
+  data->tables.fini ();
+
+  free (data);
+}
+
+static hb_blob_t *
+_hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
+{
+
+  unsigned int table_count = data->tables.length;
+  unsigned int face_length = table_count * 16 + 12;
+
+  for (unsigned int i = 0; i < table_count; i++)
+    face_length += hb_ceil_to_4 (hb_blob_get_length (data->tables[i].blob));
+
+  char *buf = (char *) malloc (face_length);
+  if (unlikely (!buf))
+    return nullptr;
+
+  hb_serialize_context_t c (buf, face_length);
+  c.propagate_error (data->tables);
+  OT::OpenTypeFontFile *f = c.start_serialize<OT::OpenTypeFontFile> ();
+
+  bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
+  hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
+
+  bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
+
+  c.end_serialize ();
+
+  if (unlikely (!ret))
+  {
+    free (buf);
+    return nullptr;
+  }
+
+  return hb_blob_create (buf, face_length, HB_MEMORY_MODE_WRITABLE, buf, free);
+}
+
+static hb_blob_t *
+_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
+{
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
+
+  if (!tag)
+    return _hb_face_builder_data_reference_blob (data);
+
+  hb_face_builder_data_t::table_entry_t *entry = data->tables.lsearch (tag);
+  if (entry)
+    return hb_blob_reference (entry->blob);
+
+  return nullptr;
+}
+
+
+/**
+ * hb_face_builder_create:
+ *
+ * Creates a #hb_face_t that can be used with hb_face_builder_add_table().
+ * After tables are added to the face, it can be compiled to a binary
+ * font file by calling hb_face_reference_blob().
+ *
+ * Return value: (transfer full): New face.
+ *
+ * Since: 1.9.0
+ **/
+hb_face_t *
+hb_face_builder_create ()
+{
+  hb_face_builder_data_t *data = _hb_face_builder_data_create ();
+  if (unlikely (!data)) return hb_face_get_empty ();
+
+  return hb_face_create_for_tables (_hb_face_builder_reference_table,
+                                    data,
+                                    _hb_face_builder_data_destroy);
+}
+
+/**
+ * hb_face_builder_add_table:
+ *
+ * Add table for @tag with data provided by @blob to the face.  @face must
+ * be created using hb_face_builder_create().
+ *
+ * Since: 1.9.0
+ **/
+hb_bool_t
+hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
+{
+  if (unlikely (face->destroy != (hb_destroy_func_t) _hb_face_builder_data_destroy))
+    return false;
+
+  hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
+  hb_face_builder_data_t::table_entry_t *entry = data->tables.push ();
+
+  entry->tag = tag;
+  entry->blob = hb_blob_reference (blob);
+
+  return true;
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.h	Tue Mar 26 09:05:10 2019 -0400
@@ -33,6 +33,7 @@
 
 #include "hb-common.h"
 #include "hb-blob.h"
+#include "hb-set.h"
 
 HB_BEGIN_DECLS
 
@@ -76,19 +77,19 @@
                        hb_bool_t           replace);
 
 HB_EXTERN void *
-hb_face_get_user_data (hb_face_t          *face,
+hb_face_get_user_data (const hb_face_t    *face,
                        hb_user_data_key_t *key);
 
 HB_EXTERN void
 hb_face_make_immutable (hb_face_t *face);
 
 HB_EXTERN hb_bool_t
-hb_face_is_immutable (hb_face_t *face);
+hb_face_is_immutable (const hb_face_t *face);
 
 
 HB_EXTERN hb_blob_t *
-hb_face_reference_table (hb_face_t *face,
-                         hb_tag_t   tag);
+hb_face_reference_table (const hb_face_t *face,
+                         hb_tag_t tag);
 
 HB_EXTERN hb_blob_t *
 hb_face_reference_blob (hb_face_t *face);
@@ -98,28 +99,60 @@
                    unsigned int  index);
 
 HB_EXTERN unsigned int
-hb_face_get_index (hb_face_t    *face);
+hb_face_get_index (const hb_face_t *face);
 
 HB_EXTERN void
 hb_face_set_upem (hb_face_t    *face,
                   unsigned int  upem);
 
 HB_EXTERN unsigned int
-hb_face_get_upem (hb_face_t *face);
+hb_face_get_upem (const hb_face_t *face);
 
 HB_EXTERN void
 hb_face_set_glyph_count (hb_face_t    *face,
                          unsigned int  glyph_count);
 
 HB_EXTERN unsigned int
-hb_face_get_glyph_count (hb_face_t *face);
+hb_face_get_glyph_count (const hb_face_t *face);
 
 HB_EXTERN unsigned int
-hb_face_get_table_tags (hb_face_t    *face,
+hb_face_get_table_tags (const hb_face_t *face,
                         unsigned int  start_offset,
                         unsigned int *table_count, /* IN/OUT */
                         hb_tag_t     *table_tags /* OUT */);
 
+
+/*
+ * Character set.
+ */
+
+HB_EXTERN void
+hb_face_collect_unicodes (hb_face_t *face,
+                          hb_set_t  *out);
+
+HB_EXTERN void
+hb_face_collect_variation_selectors (hb_face_t *face,
+                                     hb_set_t  *out);
+
+HB_EXTERN void
+hb_face_collect_variation_unicodes (hb_face_t *face,
+                                    hb_codepoint_t variation_selector,
+                                    hb_set_t  *out);
+
+
+/*
+ * Builder face.
+ */
+
+HB_EXTERN hb_face_t *
+hb_face_builder_create (void);
+
+HB_EXTERN hb_bool_t
+hb_face_builder_add_table (hb_face_t *face,
+                           hb_tag_t   tag,
+                           hb_blob_t *blob);
+
+
 HB_END_DECLS
 
 #endif /* HB_FACE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-face.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,109 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_FACE_HH
+#define HB_FACE_HH
+
+#include "hb.hh"
+
+#include "hb-shaper.hh"
+#include "hb-shape-plan.hh"
+#include "hb-ot-face.hh"
+
+
+/*
+ * hb_face_t
+ */
+
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, face);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_face_t
+{
+  hb_object_header_t header;
+
+  hb_reference_table_func_t  reference_table_func;
+  void                      *user_data;
+  hb_destroy_func_t          destroy;
+
+  unsigned int index;                   /* Face index in a collection, zero-based. */
+  mutable hb_atomic_int_t upem;         /* Units-per-EM. */
+  mutable hb_atomic_int_t num_glyphs;   /* Number of glyphs. */
+
+  hb_shaper_object_dataset_t<hb_face_t> data;/* Various shaper data. */
+  hb_ot_face_t table;                   /* All the face's tables. */
+
+  /* Cache */
+  struct plan_node_t
+  {
+    hb_shape_plan_t *shape_plan;
+    plan_node_t *next;
+  };
+  hb_atomic_ptr_t<plan_node_t> shape_plans;
+
+  hb_blob_t *reference_table (hb_tag_t tag) const
+  {
+    hb_blob_t *blob;
+
+    if (unlikely (!reference_table_func))
+      return hb_blob_get_empty ();
+
+    blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
+    if (unlikely (!blob))
+      return hb_blob_get_empty ();
+
+    return blob;
+  }
+
+  HB_PURE_FUNC unsigned int get_upem () const
+  {
+    unsigned int ret = upem.get_relaxed ();
+    if (unlikely (!ret))
+    {
+      return load_upem ();
+    }
+    return ret;
+  }
+
+  unsigned int get_num_glyphs () const
+  {
+    unsigned int ret = num_glyphs.get_relaxed ();
+    if (unlikely (ret == (unsigned int) -1))
+      return load_num_glyphs ();
+    return ret;
+  }
+
+  private:
+  HB_INTERNAL unsigned int load_upem () const;
+  HB_INTERNAL unsigned int load_num_glyphs () const;
+};
+DECLARE_NULL_INSTANCE (hb_face_t);
+
+
+#endif /* HB_FACE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-fallback-shape.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,28 +24,23 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER fallback
-#include "hb-shaper-impl-private.hh"
-
-
-HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font)
+#include "hb-shaper-impl.hh"
 
 
 /*
  * shaper face data
  */
 
-struct hb_fallback_shaper_face_data_t {};
+struct hb_fallback_face_data_t {};
 
-hb_fallback_shaper_face_data_t *
+hb_fallback_face_data_t *
 _hb_fallback_shaper_face_data_create (hb_face_t *face HB_UNUSED)
 {
-  return (hb_fallback_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_fallback_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_fallback_shaper_face_data_destroy (hb_fallback_shaper_face_data_t *data HB_UNUSED)
+_hb_fallback_shaper_face_data_destroy (hb_fallback_face_data_t *data HB_UNUSED)
 {
 }
 
@@ -54,38 +49,16 @@
  * shaper font data
  */
 
-struct hb_fallback_shaper_font_data_t {};
+struct hb_fallback_font_data_t {};
 
-hb_fallback_shaper_font_data_t *
+hb_fallback_font_data_t *
 _hb_fallback_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
-  return (hb_fallback_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_fallback_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_fallback_shaper_font_data_destroy (hb_fallback_shaper_font_data_t *data HB_UNUSED)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_fallback_shaper_shape_plan_data_t {};
-
-hb_fallback_shaper_shape_plan_data_t *
-_hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
-                                            const hb_feature_t *user_features HB_UNUSED,
-                                            unsigned int        num_user_features HB_UNUSED,
-                                            const int          *coords HB_UNUSED,
-                                            unsigned int        num_coords HB_UNUSED)
-{
-  return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_fallback_shaper_shape_plan_data_destroy (hb_fallback_shaper_shape_plan_data_t *data HB_UNUSED)
+_hb_fallback_shaper_font_data_destroy (hb_fallback_font_data_t *data HB_UNUSED)
 {
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,565 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_FONT_PRIVATE_HH
-#define HB_FONT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-object-private.hh"
-#include "hb-face-private.hh"
-#include "hb-shaper-private.hh"
-
-
-
-/*
- * hb_font_funcs_t
- */
-
-#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
-  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
-  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
-  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
-  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_name) \
-  HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
-  /* ^--- Add new callbacks here */
-
-struct hb_font_funcs_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  } user_data;
-
-  struct {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-  } destroy;
-
-  /* Don't access these directly.  Call font->get_*() instead. */
-  union get_t {
-    struct get_funcs_t {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-    } f;
-    void (*array[0
-#define HB_FONT_FUNC_IMPLEMENT(name) +1
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-                ]) (void);
-  } get;
-};
-
-
-
-/*
- * hb_font_t
- */
-
-struct hb_font_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t immutable;
-
-  hb_font_t *parent;
-  hb_face_t *face;
-
-  int x_scale;
-  int y_scale;
-
-  unsigned int x_ppem;
-  unsigned int y_ppem;
-
-  float ptem;
-
-  /* Font variation coordinates. */
-  unsigned int num_coords;
-  int *coords;
-
-  hb_font_funcs_t   *klass;
-  void              *user_data;
-  hb_destroy_func_t  destroy;
-
-  struct hb_shaper_data_t shaper_data;
-
-
-  /* Convert from font-space to user-space */
-  inline int dir_scale (hb_direction_t direction)
-  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
-  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
-  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
-  inline hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
-  inline hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
-  inline float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
-  inline float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
-  inline hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
-  { return em_scale (v, dir_scale (direction)); }
-
-  /* Convert from parent-font user-space to our user-space */
-  inline hb_position_t parent_scale_x_distance (hb_position_t v) {
-    if (unlikely (parent && parent->x_scale != x_scale))
-      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
-    return v;
-  }
-  inline hb_position_t parent_scale_y_distance (hb_position_t v) {
-    if (unlikely (parent && parent->y_scale != y_scale))
-      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
-    return v;
-  }
-  inline hb_position_t parent_scale_x_position (hb_position_t v) {
-    return parent_scale_x_distance (v);
-  }
-  inline hb_position_t parent_scale_y_position (hb_position_t v) {
-    return parent_scale_y_distance (v);
-  }
-
-  inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
-    *x = parent_scale_x_distance (*x);
-    *y = parent_scale_y_distance (*y);
-  }
-  inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
-    *x = parent_scale_x_position (*x);
-    *y = parent_scale_y_position (*y);
-  }
-
-
-  /* Public getters */
-
-  HB_INTERNAL bool has_func (unsigned int i);
-
-  /* has_* ... */
-#define HB_FONT_FUNC_IMPLEMENT(name) \
-  bool \
-  has_##name##_func (void) \
-  { \
-    hb_font_funcs_t *funcs = this->klass; \
-    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
-    return has_func (i); \
-  }
-  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
-
-  inline hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.font_h_extents (this, user_data,
-                                        extents,
-                                        klass->user_data.font_h_extents);
-  }
-  inline hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.font_v_extents (this, user_data,
-                                        extents,
-                                        klass->user_data.font_v_extents);
-  }
-
-  inline bool has_glyph (hb_codepoint_t unicode)
-  {
-    hb_codepoint_t glyph;
-    return get_nominal_glyph (unicode, &glyph);
-  }
-
-  inline hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
-                                      hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    return klass->get.f.nominal_glyph (this, user_data,
-                                       unicode, glyph,
-                                       klass->user_data.nominal_glyph);
-  }
-
-  inline hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-                                        hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    return klass->get.f.variation_glyph (this, user_data,
-                                         unicode, variation_selector, glyph,
-                                         klass->user_data.variation_glyph);
-  }
-
-  inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
-  {
-    return klass->get.f.glyph_h_advance (this, user_data,
-                                         glyph,
-                                         klass->user_data.glyph_h_advance);
-  }
-
-  inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
-  {
-    return klass->get.f.glyph_v_advance (this, user_data,
-                                         glyph,
-                                         klass->user_data.glyph_v_advance);
-  }
-
-  inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
-                                       hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_h_origin (this, user_data,
-                                        glyph, x, y,
-                                        klass->user_data.glyph_h_origin);
-  }
-
-  inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
-                                       hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_v_origin (this, user_data,
-                                        glyph, x, y,
-                                        klass->user_data.glyph_v_origin);
-  }
-
-  inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
-  {
-    return klass->get.f.glyph_h_kerning (this, user_data,
-                                         left_glyph, right_glyph,
-                                         klass->user_data.glyph_h_kerning);
-  }
-
-  inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
-  {
-    return klass->get.f.glyph_v_kerning (this, user_data,
-                                         top_glyph, bottom_glyph,
-                                         klass->user_data.glyph_v_kerning);
-  }
-
-  inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
-                                      hb_glyph_extents_t *extents)
-  {
-    memset (extents, 0, sizeof (*extents));
-    return klass->get.f.glyph_extents (this, user_data,
-                                       glyph,
-                                       extents,
-                                       klass->user_data.glyph_extents);
-  }
-
-  inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
-                                            hb_position_t *x, hb_position_t *y)
-  {
-    *x = *y = 0;
-    return klass->get.f.glyph_contour_point (this, user_data,
-                                             glyph, point_index,
-                                             x, y,
-                                             klass->user_data.glyph_contour_point);
-  }
-
-  inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
-                                   char *name, unsigned int size)
-  {
-    if (size) *name = '\0';
-    return klass->get.f.glyph_name (this, user_data,
-                                    glyph,
-                                    name, size,
-                                    klass->user_data.glyph_name);
-  }
-
-  inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
-                                        hb_codepoint_t *glyph)
-  {
-    *glyph = 0;
-    if (len == -1) len = strlen (name);
-    return klass->get.f.glyph_from_name (this, user_data,
-                                         name, len,
-                                         glyph,
-                                         klass->user_data.glyph_from_name);
-  }
-
-
-  /* A bit higher-level, and with fallback */
-
-  inline void get_h_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_h_extents (extents))
-    {
-      extents->ascender = y_scale * .8;
-      extents->descender = extents->ascender - y_scale;
-      extents->line_gap = 0;
-    }
-  }
-  inline void get_v_extents_with_fallback (hb_font_extents_t *extents)
-  {
-    if (!get_font_v_extents (extents))
-    {
-      extents->ascender = x_scale / 2;
-      extents->descender = extents->ascender - x_scale;
-      extents->line_gap = 0;
-    }
-  }
-
-  inline void get_extents_for_direction (hb_direction_t direction,
-                                         hb_font_extents_t *extents)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_h_extents_with_fallback (extents);
-    else
-      get_v_extents_with_fallback (extents);
-  }
-
-  inline void get_glyph_advance_for_direction (hb_codepoint_t glyph,
-                                               hb_direction_t direction,
-                                               hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
-      *x = get_glyph_h_advance (glyph);
-      *y = 0;
-    } else {
-      *x = 0;
-      *y = get_glyph_v_advance (glyph);
-    }
-  }
-
-  inline void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
-                                             hb_position_t *x, hb_position_t *y)
-  {
-    *x = get_glyph_h_advance (glyph) / 2;
-
-    /* TODO cache this somehow?! */
-    hb_font_extents_t extents;
-    get_h_extents_with_fallback (&extents);
-    *y = extents.ascender;
-  }
-
-  inline void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
-                                                hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_h_origin (glyph, x, y) &&
-         get_glyph_v_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x -= dx; *y -= dy;
-    }
-  }
-  inline void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
-                                                hb_position_t *x, hb_position_t *y)
-  {
-    if (!get_glyph_v_origin (glyph, x, y) &&
-         get_glyph_h_origin (glyph, x, y))
-    {
-      hb_position_t dx, dy;
-      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
-      *x += dx; *y += dy;
-    }
-  }
-
-  inline void get_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                              hb_direction_t direction,
-                                              hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
-      get_glyph_h_origin_with_fallback (glyph, x, y);
-    else
-      get_glyph_v_origin_with_fallback (glyph, x, y);
-  }
-
-  inline void add_glyph_h_origin (hb_codepoint_t glyph,
-                                  hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-  inline void add_glyph_v_origin (hb_codepoint_t glyph,
-                                  hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-  inline void add_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                              hb_direction_t direction,
-                                              hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
-
-    *x += origin_x;
-    *y += origin_y;
-  }
-
-  inline void subtract_glyph_h_origin (hb_codepoint_t glyph,
-                                       hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-  inline void subtract_glyph_v_origin (hb_codepoint_t glyph,
-                                       hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-  inline void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
-                                                   hb_direction_t direction,
-                                                   hb_position_t *x, hb_position_t *y)
-  {
-    hb_position_t origin_x, origin_y;
-
-    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
-
-    *x -= origin_x;
-    *y -= origin_y;
-  }
-
-  inline void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                               hb_direction_t direction,
-                                               hb_position_t *x, hb_position_t *y)
-  {
-    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
-      *x = get_glyph_h_kerning (first_glyph, second_glyph);
-      *y = 0;
-    } else {
-      *x = 0;
-      *y = get_glyph_v_kerning (first_glyph, second_glyph);
-    }
-  }
-
-  inline hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
-                                                 hb_direction_t direction,
-                                                 hb_glyph_extents_t *extents)
-  {
-    hb_bool_t ret = get_glyph_extents (glyph, extents);
-
-    if (ret)
-      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
-
-    return ret;
-  }
-
-  inline hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
-                                                       hb_direction_t direction,
-                                                       hb_position_t *x, hb_position_t *y)
-  {
-    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
-
-    if (ret)
-      subtract_glyph_origin_for_direction (glyph, direction, x, y);
-
-    return ret;
-  }
-
-  /* Generates gidDDD if glyph has no name. */
-  inline void
-  glyph_to_string (hb_codepoint_t glyph,
-                   char *s, unsigned int size)
-  {
-    if (get_glyph_name (glyph, s, size)) return;
-
-    if (size && snprintf (s, size, "gid%u", glyph) < 0)
-      *s = '\0';
-  }
-
-  /* Parses gidDDD and uniUUUU strings automatically. */
-  inline hb_bool_t
-  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
-                     hb_codepoint_t *glyph)
-  {
-    if (get_glyph_from_name (s, len, glyph)) return true;
-
-    if (len == -1) len = strlen (s);
-
-    /* Straight glyph index. */
-    if (hb_codepoint_parse (s, len, 10, glyph))
-      return true;
-
-    if (len > 3)
-    {
-      /* gidDDD syntax for glyph indices. */
-      if (0 == strncmp (s, "gid", 3) &&
-          hb_codepoint_parse (s + 3, len - 3, 10, glyph))
-        return true;
-
-      /* uniUUUU and other Unicode character indices. */
-      hb_codepoint_t unichar;
-      if (0 == strncmp (s, "uni", 3) &&
-          hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
-          get_nominal_glyph (unichar, glyph))
-        return true;
-    }
-
-    return false;
-  }
-
-  inline hb_position_t em_scale (int16_t v, int scale)
-  {
-    int upem = face->get_upem ();
-    int64_t scaled = v * (int64_t) scale;
-    scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
-    return (hb_position_t) (scaled / upem);
-  }
-  inline hb_position_t em_scalef (float v, int scale)
-  {
-    return (hb_position_t) round (v * scale / face->get_upem ());
-  }
-  inline float em_fscale (int16_t v, int scale)
-  {
-    return (float) v * scale / face->get_upem ();
-  }
-};
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_FONT_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,9 +26,25 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+
+#include "hb-ot.h"
+
 
-#include "hb-font-private.hh"
+/**
+ * SECTION:hb-font
+ * @title: hb-font
+ * @short_description: Font objects
+ * @include: hb.h
+ *
+ * Font objects represent a font face at a certain size and other
+ * parameters (pixels per EM, points per EM, variation settings.)
+ * Fonts are created from font faces, and are used as input to
+ * hb_shape() among other things.
+ **/
 
 
 /*
@@ -38,23 +54,23 @@
 static hb_bool_t
 hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_font_extents_t *metrics,
+                                hb_font_extents_t *extents,
                                 void *user_data HB_UNUSED)
 {
-  memset (metrics, 0, sizeof (*metrics));
+  memset (extents, 0, sizeof (*extents));
   return false;
 }
 static hb_bool_t
-hb_font_get_font_h_extents_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_font_extents_t *metrics,
-                                   void *user_data HB_UNUSED)
+hb_font_get_font_h_extents_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_font_extents_t *extents,
+                                    void *user_data HB_UNUSED)
 {
-  hb_bool_t ret = font->parent->get_font_h_extents (metrics);
+  hb_bool_t ret = font->parent->get_font_h_extents (extents);
   if (ret) {
-    metrics->ascender = font->parent_scale_y_distance (metrics->ascender);
-    metrics->descender = font->parent_scale_y_distance (metrics->descender);
-    metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap);
+    extents->ascender = font->parent_scale_y_distance (extents->ascender);
+    extents->descender = font->parent_scale_y_distance (extents->descender);
+    extents->line_gap = font->parent_scale_y_distance (extents->line_gap);
   }
   return ret;
 }
@@ -62,23 +78,23 @@
 static hb_bool_t
 hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_font_extents_t *metrics,
+                                hb_font_extents_t *extents,
                                 void *user_data HB_UNUSED)
 {
-  memset (metrics, 0, sizeof (*metrics));
+  memset (extents, 0, sizeof (*extents));
   return false;
 }
 static hb_bool_t
-hb_font_get_font_v_extents_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_font_extents_t *metrics,
-                                   void *user_data HB_UNUSED)
+hb_font_get_font_v_extents_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_font_extents_t *extents,
+                                    void *user_data HB_UNUSED)
 {
-  hb_bool_t ret = font->parent->get_font_v_extents (metrics);
+  hb_bool_t ret = font->parent->get_font_v_extents (extents);
   if (ret) {
-    metrics->ascender = font->parent_scale_x_distance (metrics->ascender);
-    metrics->descender = font->parent_scale_x_distance (metrics->descender);
-    metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap);
+    extents->ascender = font->parent_scale_x_distance (extents->ascender);
+    extents->descender = font->parent_scale_x_distance (extents->descender);
+    extents->line_gap = font->parent_scale_x_distance (extents->line_gap);
   }
   return ret;
 }
@@ -86,7 +102,7 @@
 static hb_bool_t
 hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
                                void *font_data HB_UNUSED,
-                               hb_codepoint_t unicode,
+                               hb_codepoint_t unicode HB_UNUSED,
                                hb_codepoint_t *glyph,
                                void *user_data HB_UNUSED)
 {
@@ -94,20 +110,53 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_nominal_glyph_parent (hb_font_t *font,
-                                  void *font_data HB_UNUSED,
-                                  hb_codepoint_t unicode,
-                                  hb_codepoint_t *glyph,
-                                  void *user_data HB_UNUSED)
+hb_font_get_nominal_glyph_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   hb_codepoint_t unicode,
+                                   hb_codepoint_t *glyph,
+                                   void *user_data HB_UNUSED)
 {
+  if (font->has_nominal_glyphs_func_set ())
+  {
+    return font->get_nominal_glyphs (1, &unicode, 0, glyph, 0);
+  }
   return font->parent->get_nominal_glyph (unicode, glyph);
 }
 
+#define hb_font_get_nominal_glyphs_nil hb_font_get_nominal_glyphs_default
+static unsigned int
+hb_font_get_nominal_glyphs_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    unsigned int count,
+                                    const hb_codepoint_t *first_unicode,
+                                    unsigned int unicode_stride,
+                                    hb_codepoint_t *first_glyph,
+                                    unsigned int glyph_stride,
+                                    void *user_data HB_UNUSED)
+{
+  if (font->has_nominal_glyph_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (!font->get_nominal_glyph (*first_unicode, first_glyph))
+        return i;
+
+      first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    }
+    return count;
+  }
+
+  return font->parent->get_nominal_glyphs (count,
+                                           first_unicode, unicode_stride,
+                                           first_glyph, glyph_stride);
+}
+
 static hb_bool_t
 hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t unicode,
-                                 hb_codepoint_t variation_selector,
+                                 hb_codepoint_t unicode HB_UNUSED,
+                                 hb_codepoint_t variation_selector HB_UNUSED,
                                  hb_codepoint_t *glyph,
                                  void *user_data HB_UNUSED)
 {
@@ -115,12 +164,12 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_variation_glyph_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t unicode,
-                                    hb_codepoint_t variation_selector,
-                                    hb_codepoint_t *glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_variation_glyph_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t unicode,
+                                     hb_codepoint_t variation_selector,
+                                     hb_codepoint_t *glyph,
+                                     void *user_data HB_UNUSED)
 {
   return font->parent->get_variation_glyph (unicode, variation_selector, glyph);
 }
@@ -129,42 +178,118 @@
 static hb_position_t
 hb_font_get_glyph_h_advance_nil (hb_font_t *font,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t glyph,
+                                 hb_codepoint_t glyph HB_UNUSED,
                                  void *user_data HB_UNUSED)
 {
   return font->x_scale;
 }
 static hb_position_t
-hb_font_get_glyph_h_advance_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_h_advance_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t glyph,
+                                     void *user_data HB_UNUSED)
 {
+  if (font->has_glyph_h_advances_func_set ())
+  {
+    hb_position_t ret;
+    font->get_glyph_h_advances (1, &glyph, 0, &ret, 0);
+    return ret;
+  }
   return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
 }
 
 static hb_position_t
 hb_font_get_glyph_v_advance_nil (hb_font_t *font,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t glyph,
+                                 hb_codepoint_t glyph HB_UNUSED,
                                  void *user_data HB_UNUSED)
 {
   /* TODO use font_extents.ascender+descender */
   return font->y_scale;
 }
 static hb_position_t
-hb_font_get_glyph_v_advance_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_v_advance_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t glyph,
+                                     void *user_data HB_UNUSED)
+{
+  if (font->has_glyph_v_advances_func_set ())
+  {
+    hb_position_t ret;
+    font->get_glyph_v_advances (1, &glyph, 0, &ret, 0);
+    return ret;
+  }
+  return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
+}
+
+#define hb_font_get_glyph_h_advances_nil hb_font_get_glyph_h_advances_default
+static void
+hb_font_get_glyph_h_advances_default (hb_font_t* font,
+                                      void* font_data HB_UNUSED,
+                                      unsigned int count,
+                                      const hb_codepoint_t *first_glyph,
+                                      unsigned int glyph_stride,
+                                      hb_position_t *first_advance,
+                                      unsigned int advance_stride,
+                                      void *user_data HB_UNUSED)
 {
-  return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
+  if (font->has_glyph_h_advance_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      *first_advance = font->get_glyph_h_advance (*first_glyph);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+    return;
+  }
+
+  font->parent->get_glyph_h_advances (count,
+                                      first_glyph, glyph_stride,
+                                      first_advance, advance_stride);
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->parent_scale_x_distance (*first_advance);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
+}
+
+#define hb_font_get_glyph_v_advances_nil hb_font_get_glyph_v_advances_default
+static void
+hb_font_get_glyph_v_advances_default (hb_font_t* font,
+                                      void* font_data HB_UNUSED,
+                                      unsigned int count,
+                                      const hb_codepoint_t *first_glyph,
+                                      unsigned int glyph_stride,
+                                      hb_position_t *first_advance,
+                                      unsigned int advance_stride,
+                                      void *user_data HB_UNUSED)
+{
+  if (font->has_glyph_v_advance_func_set ())
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      *first_advance = font->get_glyph_v_advance (*first_glyph);
+      first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+    }
+    return;
+  }
+
+  font->parent->get_glyph_v_advances (count,
+                                      first_glyph, glyph_stride,
+                                      first_advance, advance_stride);
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->parent_scale_y_distance (*first_advance);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
 static hb_bool_t
 hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t glyph,
+                                hb_codepoint_t glyph HB_UNUSED,
                                 hb_position_t *x,
                                 hb_position_t *y,
                                 void *user_data HB_UNUSED)
@@ -173,12 +298,12 @@
   return true;
 }
 static hb_bool_t
-hb_font_get_glyph_h_origin_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t glyph,
-                                   hb_position_t *x,
-                                   hb_position_t *y,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_h_origin_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t glyph,
+                                    hb_position_t *x,
+                                    hb_position_t *y,
+                                    void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
   if (ret)
@@ -189,7 +314,7 @@
 static hb_bool_t
 hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
                                 void *font_data HB_UNUSED,
-                                hb_codepoint_t glyph,
+                                hb_codepoint_t glyph HB_UNUSED,
                                 hb_position_t *x,
                                 hb_position_t *y,
                                 void *user_data HB_UNUSED)
@@ -198,12 +323,12 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_v_origin_parent (hb_font_t *font,
-                                   void *font_data HB_UNUSED,
-                                   hb_codepoint_t glyph,
-                                   hb_position_t *x,
-                                   hb_position_t *y,
-                                   void *user_data HB_UNUSED)
+hb_font_get_glyph_v_origin_default (hb_font_t *font,
+                                    void *font_data HB_UNUSED,
+                                    hb_codepoint_t glyph,
+                                    hb_position_t *x,
+                                    hb_position_t *y,
+                                    void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
   if (ret)
@@ -214,18 +339,18 @@
 static hb_position_t
 hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t left_glyph,
-                                 hb_codepoint_t right_glyph,
+                                 hb_codepoint_t left_glyph HB_UNUSED,
+                                 hb_codepoint_t right_glyph HB_UNUSED,
                                  void *user_data HB_UNUSED)
 {
   return 0;
 }
 static hb_position_t
-hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t left_glyph,
-                                    hb_codepoint_t right_glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_h_kerning_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t left_glyph,
+                                     hb_codepoint_t right_glyph,
+                                     void *user_data HB_UNUSED)
 {
   return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
 }
@@ -233,18 +358,18 @@
 static hb_position_t
 hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
                                  void *font_data HB_UNUSED,
-                                 hb_codepoint_t top_glyph,
-                                 hb_codepoint_t bottom_glyph,
+                                 hb_codepoint_t top_glyph HB_UNUSED,
+                                 hb_codepoint_t bottom_glyph HB_UNUSED,
                                  void *user_data HB_UNUSED)
 {
   return 0;
 }
 static hb_position_t
-hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    hb_codepoint_t top_glyph,
-                                    hb_codepoint_t bottom_glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_v_kerning_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     hb_codepoint_t top_glyph,
+                                     hb_codepoint_t bottom_glyph,
+                                     void *user_data HB_UNUSED)
 {
   return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
 }
@@ -252,7 +377,7 @@
 static hb_bool_t
 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
                                void *font_data HB_UNUSED,
-                               hb_codepoint_t glyph,
+                               hb_codepoint_t glyph HB_UNUSED,
                                hb_glyph_extents_t *extents,
                                void *user_data HB_UNUSED)
 {
@@ -260,11 +385,11 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_extents_parent (hb_font_t *font,
-                                  void *font_data HB_UNUSED,
-                                  hb_codepoint_t glyph,
-                                  hb_glyph_extents_t *extents,
-                                  void *user_data HB_UNUSED)
+hb_font_get_glyph_extents_default (hb_font_t *font,
+                                   void *font_data HB_UNUSED,
+                                   hb_codepoint_t glyph,
+                                   hb_glyph_extents_t *extents,
+                                   void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
   if (ret) {
@@ -277,8 +402,8 @@
 static hb_bool_t
 hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
                                      void *font_data HB_UNUSED,
-                                     hb_codepoint_t glyph,
-                                     unsigned int point_index,
+                                     hb_codepoint_t glyph HB_UNUSED,
+                                     unsigned int point_index HB_UNUSED,
                                      hb_position_t *x,
                                      hb_position_t *y,
                                      void *user_data HB_UNUSED)
@@ -287,13 +412,13 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_contour_point_parent (hb_font_t *font,
-                                        void *font_data HB_UNUSED,
-                                        hb_codepoint_t glyph,
-                                        unsigned int point_index,
-                                        hb_position_t *x,
-                                        hb_position_t *y,
-                                        void *user_data HB_UNUSED)
+hb_font_get_glyph_contour_point_default (hb_font_t *font,
+                                         void *font_data HB_UNUSED,
+                                         hb_codepoint_t glyph,
+                                         unsigned int point_index,
+                                         hb_position_t *x,
+                                         hb_position_t *y,
+                                         void *user_data HB_UNUSED)
 {
   hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
   if (ret)
@@ -304,7 +429,7 @@
 static hb_bool_t
 hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
                             void *font_data HB_UNUSED,
-                            hb_codepoint_t glyph,
+                            hb_codepoint_t glyph HB_UNUSED,
                             char *name, unsigned int size,
                             void *user_data HB_UNUSED)
 {
@@ -312,11 +437,11 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_name_parent (hb_font_t *font,
-                               void *font_data HB_UNUSED,
-                               hb_codepoint_t glyph,
-                               char *name, unsigned int size,
-                               void *user_data HB_UNUSED)
+hb_font_get_glyph_name_default (hb_font_t *font,
+                                void *font_data HB_UNUSED,
+                                hb_codepoint_t glyph,
+                                char *name, unsigned int size,
+                                void *user_data HB_UNUSED)
 {
   return font->parent->get_glyph_name (glyph, name, size);
 }
@@ -324,7 +449,8 @@
 static hb_bool_t
 hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
                                  void *font_data HB_UNUSED,
-                                 const char *name, int len, /* -1 means nul-terminated */
+                                 const char *name HB_UNUSED,
+                                 int len HB_UNUSED, /* -1 means nul-terminated */
                                  hb_codepoint_t *glyph,
                                  void *user_data HB_UNUSED)
 {
@@ -332,20 +458,19 @@
   return false;
 }
 static hb_bool_t
-hb_font_get_glyph_from_name_parent (hb_font_t *font,
-                                    void *font_data HB_UNUSED,
-                                    const char *name, int len, /* -1 means nul-terminated */
-                                    hb_codepoint_t *glyph,
-                                    void *user_data HB_UNUSED)
+hb_font_get_glyph_from_name_default (hb_font_t *font,
+                                     void *font_data HB_UNUSED,
+                                     const char *name, int len, /* -1 means nul-terminated */
+                                     hb_codepoint_t *glyph,
+                                     void *user_data HB_UNUSED)
 {
   return font->parent->get_glyph_from_name (name, len, glyph);
 }
 
-static const hb_font_funcs_t _hb_font_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
-
   {
 #define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -364,11 +489,10 @@
     }
   }
 };
-static const hb_font_funcs_t _hb_font_funcs_parent = {
+
+static const hb_font_funcs_t _hb_font_funcs_default = {
   HB_OBJECT_HEADER_STATIC,
 
-  true, /* immutable */
-
   {
 #define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
     HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -381,7 +505,7 @@
   },
   {
     {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
     }
@@ -399,14 +523,14 @@
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
-hb_font_funcs_create (void)
+hb_font_funcs_create ()
 {
   hb_font_funcs_t *ffuncs;
 
   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
     return hb_font_funcs_get_empty ();
 
-  ffuncs->get = _hb_font_funcs_parent.get;
+  ffuncs->get = _hb_font_funcs_default.get;
 
   return ffuncs;
 }
@@ -421,9 +545,9 @@
  * Since: 0.9.2
  **/
 hb_font_funcs_t *
-hb_font_funcs_get_empty (void)
+hb_font_funcs_get_empty ()
 {
-  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
+  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_default);
 }
 
 /**
@@ -517,10 +641,10 @@
 void
 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
 {
-  if (unlikely (hb_object_is_inert (ffuncs)))
+  if (hb_object_is_immutable (ffuncs))
     return;
 
-  ffuncs->immutable = true;
+  hb_object_make_immutable (ffuncs);
 }
 
 /**
@@ -536,7 +660,7 @@
 hb_bool_t
 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
 {
-  return ffuncs->immutable;
+  return hb_object_is_immutable (ffuncs);
 }
 
 
@@ -548,7 +672,7 @@
                                  void                        *user_data, \
                                  hb_destroy_func_t            destroy)   \
 {                                                                        \
-  if (ffuncs->immutable) {                                               \
+  if (hb_object_is_immutable (ffuncs)) {                                 \
     if (destroy)                                                         \
       destroy (user_data);                                               \
     return;                                                              \
@@ -562,9 +686,9 @@
     ffuncs->user_data.name = user_data;                                  \
     ffuncs->destroy.name = destroy;                                      \
   } else {                                                               \
-    ffuncs->get.f.name = hb_font_get_##name##_parent;                    \
-    ffuncs->user_data.name = nullptr;                                       \
-    ffuncs->destroy.name = nullptr;                                         \
+    ffuncs->get.f.name = hb_font_get_##name##_default;                   \
+    ffuncs->user_data.name = nullptr;                                    \
+    ffuncs->destroy.name = nullptr;                                      \
   }                                                                      \
 }
 
@@ -572,11 +696,16 @@
 #undef HB_FONT_FUNC_IMPLEMENT
 
 bool
+hb_font_t::has_func_set (unsigned int i)
+{
+  return this->klass->get.array[i] != _hb_font_funcs_default.get.array[i];
+}
+
+bool
 hb_font_t::has_func (unsigned int i)
 {
-  if (parent && parent != hb_font_get_empty () && parent->has_func (i))
-    return true;
-  return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
+  return has_func_set (i) ||
+         (parent && parent != &_hb_Null_hb_font_t && parent->has_func (i));
 }
 
 /* Public getters */
@@ -718,6 +847,43 @@
 }
 
 /**
+ * hb_font_get_glyph_h_advances:
+ * @font: a font.
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+void
+hb_font_get_glyph_h_advances (hb_font_t* font,
+                              unsigned int count,
+                              const hb_codepoint_t *first_glyph,
+                              unsigned glyph_stride,
+                              hb_position_t *first_advance,
+                              unsigned advance_stride)
+{
+  font->get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
+/**
+ * hb_font_get_glyph_v_advances:
+ * @font: a font.
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+void
+hb_font_get_glyph_v_advances (hb_font_t* font,
+                              unsigned int count,
+                              const hb_codepoint_t *first_glyph,
+                              unsigned glyph_stride,
+                              hb_position_t *first_advance,
+                              unsigned advance_stride)
+{
+  font->get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
+
+/**
  * hb_font_get_glyph_h_origin:
  * @font: a font.
  * @glyph:
@@ -770,6 +936,7 @@
  * Return value:
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 hb_position_t
 hb_font_get_glyph_h_kerning (hb_font_t *font,
@@ -789,6 +956,7 @@
  * Return value:
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 hb_position_t
 hb_font_get_glyph_v_kerning (hb_font_t *font,
@@ -888,7 +1056,7 @@
  * hb_font_get_extents_for_direction:
  * @font: a font.
  * @direction:
- * @extents:
+ * @extents: (out):
  *
  *
  *
@@ -921,6 +1089,26 @@
 {
   return font->get_glyph_advance_for_direction (glyph, direction, x, y);
 }
+/**
+ * hb_font_get_glyph_advances_for_direction:
+ * @font: a font.
+ * @direction:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_get_glyph_advances_for_direction (hb_font_t* font,
+                                          hb_direction_t direction,
+                                          unsigned int count,
+                                          const hb_codepoint_t *first_glyph,
+                                          unsigned glyph_stride,
+                                          hb_position_t *first_advance,
+                                          unsigned advance_stride)
+{
+  font->get_glyph_advances_for_direction (direction, count, first_glyph, glyph_stride, first_advance, advance_stride);
+}
 
 /**
  * hb_font_get_glyph_origin_for_direction:
@@ -997,6 +1185,7 @@
  *
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 void
 hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
@@ -1100,6 +1289,49 @@
  * hb_font_t
  */
 
+DEFINE_NULL_INSTANCE (hb_font_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  nullptr, /* parent */
+  const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
+
+  1000, /* x_scale */
+  1000, /* y_scale */
+
+  0, /* x_ppem */
+  0, /* y_ppem */
+  0, /* ptem */
+
+  0, /* num_coords */
+  nullptr, /* coords */
+
+  const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t),
+
+  /* Zero for the rest is fine. */
+};
+
+
+static hb_font_t *
+_hb_font_create (hb_face_t *face)
+{
+  hb_font_t *font;
+
+  if (unlikely (!face))
+    face = hb_face_get_empty ();
+  if (!(font = hb_object_create<hb_font_t> ()))
+    return hb_font_get_empty ();
+
+  hb_face_make_immutable (face);
+  font->parent = hb_font_get_empty ();
+  font->face = hb_face_reference (face);
+  font->klass = hb_font_funcs_get_empty ();
+  font->data.init0 (font);
+  font->x_scale = font->y_scale = hb_face_get_upem (face);
+
+  return font;
+}
+
 /**
  * hb_font_create: (Xconstructor)
  * @face: a face.
@@ -1113,19 +1345,10 @@
 hb_font_t *
 hb_font_create (hb_face_t *face)
 {
-  hb_font_t *font;
-
-  if (unlikely (!face))
-    face = hb_face_get_empty ();
-  if (!(font = hb_object_create<hb_font_t> ()))
-    return hb_font_get_empty ();
+  hb_font_t *font = _hb_font_create (face);
 
-  hb_face_make_immutable (face);
-  font->parent = hb_font_get_empty ();
-  font->face = hb_face_reference (face);
-  font->klass = hb_font_funcs_get_empty ();
-
-  font->x_scale = font->y_scale = hb_face_get_upem (face);
+  /* Install our in-house, very lightweight, funcs. */
+  hb_ot_font_set_funcs (font);
 
   return font;
 }
@@ -1146,9 +1369,9 @@
   if (unlikely (!parent))
     parent = hb_font_get_empty ();
 
-  hb_font_t *font = hb_font_create (parent->face);
+  hb_font_t *font = _hb_font_create (parent->face);
 
-  if (unlikely (hb_object_is_inert (font)))
+  if (unlikely (hb_object_is_immutable (font)))
     return font;
 
   font->parent = hb_font_reference (parent);
@@ -1185,38 +1408,9 @@
  * Since: 0.9.2
  **/
 hb_font_t *
-hb_font_get_empty (void)
+hb_font_get_empty ()
 {
-  static const hb_font_t _hb_font_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* parent */
-    const_cast<hb_face_t *> (&_hb_face_nil),
-
-    1000, /* x_scale */
-    1000, /* y_scale */
-
-    0, /* x_ppem */
-    0, /* y_ppem */
-    0, /* ptem */
-
-    0, /* num_coords */
-    nullptr, /* coords */
-
-    const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
-    nullptr, /* user_data */
-    nullptr, /* destroy */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_font_t *> (&_hb_font_nil);
+  return const_cast<hb_font_t *> (&Null(hb_font_t));
 }
 
 /**
@@ -1248,9 +1442,7 @@
 {
   if (!hb_object_destroy (font)) return;
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  font->data.fini ();
 
   if (font->destroy)
     font->destroy (font->user_data);
@@ -1317,13 +1509,13 @@
 void
 hb_font_make_immutable (hb_font_t *font)
 {
-  if (unlikely (hb_object_is_inert (font)))
+  if (hb_object_is_immutable (font))
     return;
 
   if (font->parent)
     hb_font_make_immutable (font->parent);
 
-  font->immutable = true;
+  hb_object_make_immutable (font);
 }
 
 /**
@@ -1339,7 +1531,7 @@
 hb_bool_t
 hb_font_is_immutable (hb_font_t *font)
 {
-  return font->immutable;
+  return hb_object_is_immutable (font);
 }
 
 /**
@@ -1355,7 +1547,7 @@
 hb_font_set_parent (hb_font_t *font,
                     hb_font_t *parent)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (!parent)
@@ -1397,7 +1589,7 @@
 hb_font_set_face (hb_font_t *font,
                   hb_face_t *face)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (unlikely (!face))
@@ -1444,7 +1636,8 @@
                    void              *font_data,
                    hb_destroy_func_t  destroy)
 {
-  if (font->immutable) {
+  if (hb_object_is_immutable (font))
+  {
     if (destroy)
       destroy (font_data);
     return;
@@ -1479,7 +1672,8 @@
                         hb_destroy_func_t  destroy)
 {
   /* Destroy user_data? */
-  if (font->immutable) {
+  if (hb_object_is_immutable (font))
+  {
     if (destroy)
       destroy (font_data);
     return;
@@ -1508,7 +1702,7 @@
                    int x_scale,
                    int y_scale)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->x_scale = x_scale;
@@ -1549,7 +1743,7 @@
                   unsigned int x_ppem,
                   unsigned int y_ppem)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->x_ppem = x_ppem;
@@ -1578,16 +1772,18 @@
 /**
  * hb_font_set_ptem:
  * @font: a font.
- * @ptem:
+ * @ptem: font size in points.
  *
- * Sets "point size" of the font.
+ * Sets "point size" of the font.  Set to 0 to unset.
+ *
+ * There are 72 points in an inch.
  *
  * Since: 1.6.0
  **/
 void
 hb_font_set_ptem (hb_font_t *font, float ptem)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   font->ptem = ptem;
@@ -1634,7 +1830,7 @@
                         const hb_variation_t *variations,
                         unsigned int variations_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (!variations_length)
@@ -1665,7 +1861,7 @@
                                const float *coords,
                                unsigned int coords_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
@@ -1686,7 +1882,7 @@
                                    const int *coords, /* 2.14 normalized */
                                    unsigned int coords_length)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   int *copy = coords_length ? (int *) calloc (coords_length, sizeof (coords[0])) : nullptr;
@@ -1718,8 +1914,6 @@
 }
 
 
-#ifndef HB_DISABLE_DEPRECATED
-
 /*
  * Deprecated get_glyph_func():
  */
@@ -1806,9 +2000,9 @@
 /**
  * hb_font_funcs_set_glyph_func:
  * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
+ * @func: (closure user_data) (destroy destroy) (scope notified): callback function.
+ * @user_data: data to pass to @func.
+ * @destroy: function to call when @user_data is not needed anymore.
  *
  * Deprecated.  Use hb_font_funcs_set_nominal_glyph_func() and
  * hb_font_funcs_set_variation_glyph_func() instead.
@@ -1842,5 +2036,3 @@
                                           trampoline,
                                           trampoline_destroy);
 }
-
-#endif /* HB_DISABLE_DEPRECATED */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.h	Tue Mar 26 09:05:10 2019 -0400
@@ -110,7 +110,7 @@
 /* func types */
 
 typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
-                                                       hb_font_extents_t *metrics,
+                                                       hb_font_extents_t *extents,
                                                        void *user_data);
 typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
 typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
@@ -125,6 +125,14 @@
                                                          hb_codepoint_t *glyph,
                                                          void *user_data);
 
+typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data,
+                                                           unsigned int count,
+                                                           const hb_codepoint_t *first_unicode,
+                                                           unsigned int unicode_stride,
+                                                           hb_codepoint_t *first_glyph,
+                                                           unsigned int glyph_stride,
+                                                           void *user_data);
+
 
 typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data,
                                                            hb_codepoint_t glyph,
@@ -132,6 +140,16 @@
 typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_h_advance_func_t;
 typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t;
 
+typedef void (*hb_font_get_glyph_advances_func_t) (hb_font_t* font, void* font_data,
+                                                   unsigned int count,
+                                                   const hb_codepoint_t *first_glyph,
+                                                   unsigned glyph_stride,
+                                                   hb_position_t *first_advance,
+                                                   unsigned advance_stride,
+                                                   void *user_data);
+typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_h_advances_func_t;
+typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
+
 typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
                                                       hb_codepoint_t glyph,
                                                       hb_position_t *x, hb_position_t *y,
@@ -139,12 +157,6 @@
 typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
 typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
 
-typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
-                                                           hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                                           void *user_data);
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
-typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
-
 
 typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
                                                        hb_codepoint_t glyph,
@@ -217,6 +229,22 @@
                                       void *user_data, hb_destroy_func_t destroy);
 
 /**
+ * hb_font_funcs_set_nominal_glyphs_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 2.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs,
+                                       hb_font_get_nominal_glyphs_func_t func,
+                                       void *user_data, hb_destroy_func_t destroy);
+
+/**
  * hb_font_funcs_set_variation_glyph_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -265,6 +293,38 @@
                                         void *user_data, hb_destroy_func_t destroy);
 
 /**
+ * hb_font_funcs_set_glyph_h_advances_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs,
+                                        hb_font_get_glyph_h_advances_func_t func,
+                                        void *user_data, hb_destroy_func_t destroy);
+
+/**
+ * hb_font_funcs_set_glyph_v_advances_func:
+ * @ffuncs: font functions.
+ * @func: (closure user_data) (destroy destroy) (scope notified):
+ * @user_data:
+ * @destroy:
+ *
+ *
+ *
+ * Since: 1.8.6
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs,
+                                        hb_font_get_glyph_v_advances_func_t func,
+                                        void *user_data, hb_destroy_func_t destroy);
+
+/**
  * hb_font_funcs_set_glyph_h_origin_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -297,38 +357,6 @@
                                        void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_font_funcs_set_glyph_h_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
-                                        hb_font_get_glyph_h_kerning_func_t func,
-                                        void *user_data, hb_destroy_func_t destroy);
-
-/**
- * hb_font_funcs_set_glyph_v_kerning_func:
- * @ffuncs: font functions.
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
-                                        hb_font_get_glyph_v_kerning_func_t func,
-                                        void *user_data, hb_destroy_func_t destroy);
-
-/**
  * hb_font_funcs_set_glyph_extents_func:
  * @ffuncs: font functions.
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -417,6 +445,21 @@
 hb_font_get_glyph_v_advance (hb_font_t *font,
                              hb_codepoint_t glyph);
 
+HB_EXTERN void
+hb_font_get_glyph_h_advances (hb_font_t* font,
+                              unsigned int count,
+                              const hb_codepoint_t *first_glyph,
+                              unsigned glyph_stride,
+                              hb_position_t *first_advance,
+                              unsigned advance_stride);
+HB_EXTERN void
+hb_font_get_glyph_v_advances (hb_font_t* font,
+                              unsigned int count,
+                              const hb_codepoint_t *first_glyph,
+                              unsigned glyph_stride,
+                              hb_position_t *first_advance,
+                              unsigned advance_stride);
+
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_h_origin (hb_font_t *font,
                             hb_codepoint_t glyph,
@@ -426,13 +469,6 @@
                             hb_codepoint_t glyph,
                             hb_position_t *x, hb_position_t *y);
 
-HB_EXTERN hb_position_t
-hb_font_get_glyph_h_kerning (hb_font_t *font,
-                             hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
-HB_EXTERN hb_position_t
-hb_font_get_glyph_v_kerning (hb_font_t *font,
-                             hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
-
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents (hb_font_t *font,
                            hb_codepoint_t glyph,
@@ -472,6 +508,14 @@
                                          hb_direction_t direction,
                                          hb_position_t *x, hb_position_t *y);
 HB_EXTERN void
+hb_font_get_glyph_advances_for_direction (hb_font_t* font,
+                                          hb_direction_t direction,
+                                          unsigned int count,
+                                          const hb_codepoint_t *first_glyph,
+                                          unsigned glyph_stride,
+                                          hb_position_t *first_advance,
+                                          unsigned advance_stride);
+HB_EXTERN void
 hb_font_get_glyph_origin_for_direction (hb_font_t *font,
                                         hb_codepoint_t glyph,
                                         hb_direction_t direction,
@@ -487,12 +531,6 @@
                                              hb_direction_t direction,
                                              hb_position_t *x, hb_position_t *y);
 
-HB_EXTERN void
-hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
-                                         hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-                                         hb_direction_t direction,
-                                         hb_position_t *x, hb_position_t *y);
-
 HB_EXTERN hb_bool_t
 hb_font_get_glyph_extents_for_origin (hb_font_t *font,
                                       hb_codepoint_t glyph,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-font.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,617 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_FONT_HH
+#define HB_FONT_HH
+
+#include "hb.hh"
+
+#include "hb-face.hh"
+#include "hb-shaper.hh"
+
+
+/*
+ * hb_font_funcs_t
+ */
+
+#define HB_FONT_FUNCS_IMPLEMENT_CALLBACKS \
+  HB_FONT_FUNC_IMPLEMENT (font_h_extents) \
+  HB_FONT_FUNC_IMPLEMENT (font_v_extents) \
+  HB_FONT_FUNC_IMPLEMENT (nominal_glyph) \
+  HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
+  HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_name) \
+  HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
+  /* ^--- Add new callbacks here */
+
+struct hb_font_funcs_t
+{
+  hb_object_header_t header;
+
+  struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
+    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+  } user_data;
+
+  struct {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+  } destroy;
+
+  /* Don't access these directly.  Call font->get_*() instead. */
+  union get_t {
+    struct get_funcs_t {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
+      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+    } f;
+    void (*array[0
+#define HB_FONT_FUNC_IMPLEMENT(name) +1
+      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+                ]) ();
+  } get;
+};
+DECLARE_NULL_INSTANCE (hb_font_funcs_t);
+
+
+/*
+ * hb_font_t
+ */
+
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_font_t
+{
+  hb_object_header_t header;
+
+  hb_font_t *parent;
+  hb_face_t *face;
+
+  int x_scale;
+  int y_scale;
+
+  unsigned int x_ppem;
+  unsigned int y_ppem;
+
+  float ptem;
+
+  /* Font variation coordinates. */
+  unsigned int num_coords;
+  int *coords;
+
+  hb_font_funcs_t   *klass;
+  void              *user_data;
+  hb_destroy_func_t  destroy;
+
+  hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
+
+
+  /* Convert from font-space to user-space */
+  int dir_scale (hb_direction_t direction)
+  { return HB_DIRECTION_IS_VERTICAL(direction) ? y_scale : x_scale; }
+  hb_position_t em_scale_x (int16_t v) { return em_scale (v, x_scale); }
+  hb_position_t em_scale_y (int16_t v) { return em_scale (v, y_scale); }
+  hb_position_t em_scalef_x (float v) { return em_scalef (v, this->x_scale); }
+  hb_position_t em_scalef_y (float v) { return em_scalef (v, this->y_scale); }
+  float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
+  float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
+  hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
+  { return em_scale (v, dir_scale (direction)); }
+
+  /* Convert from parent-font user-space to our user-space */
+  hb_position_t parent_scale_x_distance (hb_position_t v)
+  {
+    if (unlikely (parent && parent->x_scale != x_scale))
+      return (hb_position_t) (v * (int64_t) this->x_scale / this->parent->x_scale);
+    return v;
+  }
+  hb_position_t parent_scale_y_distance (hb_position_t v)
+  {
+    if (unlikely (parent && parent->y_scale != y_scale))
+      return (hb_position_t) (v * (int64_t) this->y_scale / this->parent->y_scale);
+    return v;
+  }
+  hb_position_t parent_scale_x_position (hb_position_t v)
+  { return parent_scale_x_distance (v); }
+  hb_position_t parent_scale_y_position (hb_position_t v)
+  { return parent_scale_y_distance (v); }
+
+  void parent_scale_distance (hb_position_t *x, hb_position_t *y)
+  {
+    *x = parent_scale_x_distance (*x);
+    *y = parent_scale_y_distance (*y);
+  }
+  void parent_scale_position (hb_position_t *x, hb_position_t *y)
+  {
+    *x = parent_scale_x_position (*x);
+    *y = parent_scale_y_position (*y);
+  }
+
+
+  /* Public getters */
+
+  HB_INTERNAL bool has_func (unsigned int i);
+  HB_INTERNAL bool has_func_set (unsigned int i);
+
+  /* has_* ... */
+#define HB_FONT_FUNC_IMPLEMENT(name) \
+  bool \
+  has_##name##_func () \
+  { \
+    hb_font_funcs_t *funcs = this->klass; \
+    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
+    return has_func (i); \
+  } \
+  bool \
+  has_##name##_func_set () \
+  { \
+    hb_font_funcs_t *funcs = this->klass; \
+    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
+    return has_func_set (i); \
+  }
+  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+
+  hb_bool_t get_font_h_extents (hb_font_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.font_h_extents (this, user_data,
+                                        extents,
+                                        klass->user_data.font_h_extents);
+  }
+  hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.font_v_extents (this, user_data,
+                                        extents,
+                                        klass->user_data.font_v_extents);
+  }
+
+  bool has_glyph (hb_codepoint_t unicode)
+  {
+    hb_codepoint_t glyph;
+    return get_nominal_glyph (unicode, &glyph);
+  }
+
+  hb_bool_t get_nominal_glyph (hb_codepoint_t unicode,
+                                      hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    return klass->get.f.nominal_glyph (this, user_data,
+                                       unicode, glyph,
+                                       klass->user_data.nominal_glyph);
+  }
+  unsigned int get_nominal_glyphs (unsigned int count,
+                                   const hb_codepoint_t *first_unicode,
+                                   unsigned int unicode_stride,
+                                   hb_codepoint_t *first_glyph,
+                                   unsigned int glyph_stride)
+  {
+    return klass->get.f.nominal_glyphs (this, user_data,
+                                        count,
+                                        first_unicode, unicode_stride,
+                                        first_glyph, glyph_stride,
+                                        klass->user_data.nominal_glyphs);
+  }
+
+  hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+                                 hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    return klass->get.f.variation_glyph (this, user_data,
+                                         unicode, variation_selector, glyph,
+                                         klass->user_data.variation_glyph);
+  }
+
+  hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
+  {
+    return klass->get.f.glyph_h_advance (this, user_data,
+                                         glyph,
+                                         klass->user_data.glyph_h_advance);
+  }
+
+  hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
+  {
+    return klass->get.f.glyph_v_advance (this, user_data,
+                                         glyph,
+                                         klass->user_data.glyph_v_advance);
+  }
+
+  void get_glyph_h_advances (unsigned int count,
+                             const hb_codepoint_t *first_glyph,
+                             unsigned int glyph_stride,
+                             hb_position_t *first_advance,
+                             unsigned int advance_stride)
+  {
+    return klass->get.f.glyph_h_advances (this, user_data,
+                                          count,
+                                          first_glyph, glyph_stride,
+                                          first_advance, advance_stride,
+                                          klass->user_data.glyph_h_advances);
+  }
+
+  void get_glyph_v_advances (unsigned int count,
+                             const hb_codepoint_t *first_glyph,
+                             unsigned int glyph_stride,
+                             hb_position_t *first_advance,
+                             unsigned int advance_stride)
+  {
+    return klass->get.f.glyph_v_advances (this, user_data,
+                                          count,
+                                          first_glyph, glyph_stride,
+                                          first_advance, advance_stride,
+                                          klass->user_data.glyph_v_advances);
+  }
+
+  hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
+                                       hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_h_origin (this, user_data,
+                                        glyph, x, y,
+                                        klass->user_data.glyph_h_origin);
+  }
+
+  hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
+                                hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_v_origin (this, user_data,
+                                        glyph, x, y,
+                                        klass->user_data.glyph_v_origin);
+  }
+
+  hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
+                                     hb_codepoint_t right_glyph)
+  {
+    return klass->get.f.glyph_h_kerning (this, user_data,
+                                         left_glyph, right_glyph,
+                                         klass->user_data.glyph_h_kerning);
+  }
+
+  hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
+                                     hb_codepoint_t bottom_glyph)
+  {
+    return klass->get.f.glyph_v_kerning (this, user_data,
+                                         top_glyph, bottom_glyph,
+                                         klass->user_data.glyph_v_kerning);
+  }
+
+  hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
+                                      hb_glyph_extents_t *extents)
+  {
+    memset (extents, 0, sizeof (*extents));
+    return klass->get.f.glyph_extents (this, user_data,
+                                       glyph,
+                                       extents,
+                                       klass->user_data.glyph_extents);
+  }
+
+  hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
+                                            hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    return klass->get.f.glyph_contour_point (this, user_data,
+                                             glyph, point_index,
+                                             x, y,
+                                             klass->user_data.glyph_contour_point);
+  }
+
+  hb_bool_t get_glyph_name (hb_codepoint_t glyph,
+                            char *name, unsigned int size)
+  {
+    if (size) *name = '\0';
+    return klass->get.f.glyph_name (this, user_data,
+                                    glyph,
+                                    name, size,
+                                    klass->user_data.glyph_name);
+  }
+
+  hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
+                                 hb_codepoint_t *glyph)
+  {
+    *glyph = 0;
+    if (len == -1) len = strlen (name);
+    return klass->get.f.glyph_from_name (this, user_data,
+                                         name, len,
+                                         glyph,
+                                         klass->user_data.glyph_from_name);
+  }
+
+
+  /* A bit higher-level, and with fallback */
+
+  void get_h_extents_with_fallback (hb_font_extents_t *extents)
+  {
+    if (!get_font_h_extents (extents))
+    {
+      extents->ascender = y_scale * .8;
+      extents->descender = extents->ascender - y_scale;
+      extents->line_gap = 0;
+    }
+  }
+  void get_v_extents_with_fallback (hb_font_extents_t *extents)
+  {
+    if (!get_font_v_extents (extents))
+    {
+      extents->ascender = x_scale / 2;
+      extents->descender = extents->ascender - x_scale;
+      extents->line_gap = 0;
+    }
+  }
+
+  void get_extents_for_direction (hb_direction_t direction,
+                                  hb_font_extents_t *extents)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_h_extents_with_fallback (extents);
+    else
+      get_v_extents_with_fallback (extents);
+  }
+
+  void get_glyph_advance_for_direction (hb_codepoint_t glyph,
+                                        hb_direction_t direction,
+                                        hb_position_t *x, hb_position_t *y)
+  {
+    *x = *y = 0;
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      *x = get_glyph_h_advance (glyph);
+    else
+      *y = get_glyph_v_advance (glyph);
+  }
+  void get_glyph_advances_for_direction (hb_direction_t direction,
+                                         unsigned int count,
+                                         const hb_codepoint_t *first_glyph,
+                                         unsigned glyph_stride,
+                                         hb_position_t *first_advance,
+                                         unsigned advance_stride)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_glyph_h_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+    else
+      get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
+  }
+
+  void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
+                                      hb_position_t *x, hb_position_t *y)
+  {
+    *x = get_glyph_h_advance (glyph) / 2;
+
+    /* TODO cache this somehow?! */
+    hb_font_extents_t extents;
+    get_h_extents_with_fallback (&extents);
+    *y = extents.ascender;
+  }
+
+  void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
+                                         hb_position_t *x, hb_position_t *y)
+  {
+    if (!get_glyph_h_origin (glyph, x, y) &&
+         get_glyph_v_origin (glyph, x, y))
+    {
+      hb_position_t dx, dy;
+      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+      *x -= dx; *y -= dy;
+    }
+  }
+  void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
+                                         hb_position_t *x, hb_position_t *y)
+  {
+    if (!get_glyph_v_origin (glyph, x, y) &&
+         get_glyph_h_origin (glyph, x, y))
+    {
+      hb_position_t dx, dy;
+      guess_v_origin_minus_h_origin (glyph, &dx, &dy);
+      *x += dx; *y += dy;
+    }
+  }
+
+  void get_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                       hb_direction_t direction,
+                                       hb_position_t *x, hb_position_t *y)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction)))
+      get_glyph_h_origin_with_fallback (glyph, x, y);
+    else
+      get_glyph_v_origin_with_fallback (glyph, x, y);
+  }
+
+  void add_glyph_h_origin (hb_codepoint_t glyph,
+                           hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+  void add_glyph_v_origin (hb_codepoint_t glyph,
+                           hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+  void add_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                       hb_direction_t direction,
+                                       hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
+
+    *x += origin_x;
+    *y += origin_y;
+  }
+
+  void subtract_glyph_h_origin (hb_codepoint_t glyph,
+                                hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+  void subtract_glyph_v_origin (hb_codepoint_t glyph,
+                                hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+  void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
+                                            hb_direction_t direction,
+                                            hb_position_t *x, hb_position_t *y)
+  {
+    hb_position_t origin_x, origin_y;
+
+    get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
+
+    *x -= origin_x;
+    *y -= origin_y;
+  }
+
+  void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+                                        hb_direction_t direction,
+                                        hb_position_t *x, hb_position_t *y)
+  {
+    if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) {
+      *y = 0;
+      *x = get_glyph_h_kerning (first_glyph, second_glyph);
+    } else {
+      *x = 0;
+      *y = get_glyph_v_kerning (first_glyph, second_glyph);
+    }
+  }
+
+  hb_bool_t get_glyph_extents_for_origin (hb_codepoint_t glyph,
+                                          hb_direction_t direction,
+                                          hb_glyph_extents_t *extents)
+  {
+    hb_bool_t ret = get_glyph_extents (glyph, extents);
+
+    if (ret)
+      subtract_glyph_origin_for_direction (glyph, direction, &extents->x_bearing, &extents->y_bearing);
+
+    return ret;
+  }
+
+  hb_bool_t get_glyph_contour_point_for_origin (hb_codepoint_t glyph, unsigned int point_index,
+                                                hb_direction_t direction,
+                                                hb_position_t *x, hb_position_t *y)
+  {
+    hb_bool_t ret = get_glyph_contour_point (glyph, point_index, x, y);
+
+    if (ret)
+      subtract_glyph_origin_for_direction (glyph, direction, x, y);
+
+    return ret;
+  }
+
+  /* Generates gidDDD if glyph has no name. */
+  void
+  glyph_to_string (hb_codepoint_t glyph,
+                   char *s, unsigned int size)
+  {
+    if (get_glyph_name (glyph, s, size)) return;
+
+    if (size && snprintf (s, size, "gid%u", glyph) < 0)
+      *s = '\0';
+  }
+
+  /* Parses gidDDD and uniUUUU strings automatically. */
+  hb_bool_t
+  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
+                     hb_codepoint_t *glyph)
+  {
+    if (get_glyph_from_name (s, len, glyph)) return true;
+
+    if (len == -1) len = strlen (s);
+
+    /* Straight glyph index. */
+    if (hb_codepoint_parse (s, len, 10, glyph))
+      return true;
+
+    if (len > 3)
+    {
+      /* gidDDD syntax for glyph indices. */
+      if (0 == strncmp (s, "gid", 3) &&
+          hb_codepoint_parse (s + 3, len - 3, 10, glyph))
+        return true;
+
+      /* uniUUUU and other Unicode character indices. */
+      hb_codepoint_t unichar;
+      if (0 == strncmp (s, "uni", 3) &&
+          hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
+          get_nominal_glyph (unichar, glyph))
+        return true;
+    }
+
+    return false;
+  }
+
+  hb_position_t em_scale (int16_t v, int scale)
+  {
+    int upem = face->get_upem ();
+    int64_t scaled = v * (int64_t) scale;
+    scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
+    return (hb_position_t) (scaled / upem);
+  }
+  hb_position_t em_scalef (float v, int scale)
+  { return (hb_position_t) round (v * scale / face->get_upem ()); }
+  float em_fscale (int16_t v, int scale)
+  { return (float) v * scale / face->get_upem (); }
+};
+DECLARE_NULL_INSTANCE (hb_font_t);
+
+
+#endif /* HB_FONT_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ft.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -27,47 +27,58 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
+#include "hb.hh"
 
 #include "hb-ft.h"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+#include "hb-cache.hh"
 
 #include FT_ADVANCES_H
 #include FT_MULTIPLE_MASTERS_H
 #include FT_TRUETYPE_TABLES_H
 
 
+/**
+ * SECTION:hb-ft
+ * @title: hb-ft
+ * @short_description: FreeType integration
+ * @include: hb-ft.h
+ *
+ * Functions for using HarfBuzz with the FreeType library to provide face and
+ * font data.
+ **/
+
+
 /* TODO:
  *
  * In general, this file does a fine job of what it's supposed to do.
  * There are, however, things that need more work:
  *
- *   - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy.
- *     Have not investigated.
- *
  *   - FreeType works in 26.6 mode.  Clients can decide to use that mode, and everything
  *     would work fine.  However, we also abuse this API for performing in font-space,
  *     but don't pass the correct flags to FreeType.  We just abuse the no-hinting mode
  *     for that, such that no rounding etc happens.  As such, we don't set ppem, and
  *     pass NO_HINTING as load_flags.  Would be much better to use NO_SCALE, and scale
- *     ourselves, like we do in uniscribe, etc.
+ *     ourselves.
  *
  *   - We don't handle / allow for emboldening / obliqueing.
  *
  *   - In the future, we should add constructors to create fonts in font space?
- *
- *   - FT_Load_Glyph() is extremely costly.  Do something about it?
  */
 
 
 struct hb_ft_font_t
 {
+  mutable hb_mutex_t lock;
   FT_Face ft_face;
   int load_flags;
   bool symbol; /* Whether selected cmap is symbol cmap. */
   bool unref; /* Whether to destroy ft_face when done. */
+
+  mutable hb_atomic_int_t cached_x_scale;
+  mutable hb_advance_cache_t advance_cache;
 };
 
 static hb_ft_font_t *
@@ -78,12 +89,16 @@
   if (unlikely (!ft_font))
     return nullptr;
 
+  ft_font->lock.init ();
   ft_font->ft_face = ft_face;
   ft_font->symbol = symbol;
   ft_font->unref = unref;
 
   ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
 
+  ft_font->cached_x_scale.set (0);
+  ft_font->advance_cache.init ();
+
   return ft_font;
 }
 
@@ -98,9 +113,13 @@
 {
   hb_ft_font_t *ft_font = (hb_ft_font_t *) data;
 
+  ft_font->advance_cache.fini ();
+
   if (ft_font->unref)
     _hb_ft_face_destroy (ft_font->ft_face);
 
+  ft_font->lock.fini ();
+
   free (ft_font);
 }
 
@@ -116,7 +135,7 @@
 void
 hb_ft_font_set_load_flags (hb_font_t *font, int load_flags)
 {
-  if (font->immutable)
+  if (hb_object_is_immutable (font))
     return;
 
   if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
@@ -168,6 +187,7 @@
                          void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode);
 
   if (unlikely (!g))
@@ -191,6 +211,32 @@
   return true;
 }
 
+static unsigned int
+hb_ft_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+                          void *font_data,
+                          unsigned int count,
+                          const hb_codepoint_t *first_unicode,
+                          unsigned int unicode_stride,
+                          hb_codepoint_t *first_glyph,
+                          unsigned int glyph_stride,
+                          void *user_data HB_UNUSED)
+{
+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
+  unsigned int done;
+  for (done = 0;
+       done < count && (*first_glyph = FT_Get_Char_Index (ft_font->ft_face, *first_unicode));
+       done++)
+  {
+    first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+  }
+  /* We don't need to do ft_font->symbol dance here, since HB calls the singular
+   * nominal_glyph() for what we don't handle here. */
+  return done;
+}
+
+
 static hb_bool_t
 hb_ft_get_variation_glyph (hb_font_t *font HB_UNUSED,
                            void *font_data,
@@ -200,6 +246,7 @@
                            void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   unsigned int g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector);
 
   if (unlikely (!g))
@@ -209,22 +256,45 @@
   return true;
 }
 
-static hb_position_t
-hb_ft_get_glyph_h_advance (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t glyph,
-                           void *user_data HB_UNUSED)
+static void
+hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
+                            unsigned count,
+                            const hb_codepoint_t *first_glyph,
+                            unsigned glyph_stride,
+                            hb_position_t *first_advance,
+                            unsigned advance_stride,
+                            void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Fixed v;
+  hb_lock_t lock (ft_font->lock);
+  FT_Face ft_face = ft_font->ft_face;
+  int load_flags = ft_font->load_flags;
+  int mult = font->x_scale < 0 ? -1 : +1;
 
-  if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v)))
-    return 0;
+  if (font->x_scale != ft_font->cached_x_scale.get ())
+  {
+    ft_font->advance_cache.clear ();
+    ft_font->cached_x_scale.set (font->x_scale);
+  }
 
-  if (font->x_scale < 0)
-    v = -v;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    FT_Fixed v = 0;
+    hb_codepoint_t glyph = *first_glyph;
 
-  return (v + (1<<9)) >> 10;
+    unsigned int cv;
+    if (ft_font->advance_cache.get (glyph, &cv))
+      v = cv;
+    else
+    {
+      FT_Get_Advance (ft_face, glyph, load_flags, &v);
+      ft_font->advance_cache.set (glyph, v);
+    }
+
+    *first_advance = (v * mult + (1<<9)) >> 10;
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
 static hb_position_t
@@ -234,6 +304,7 @@
                            void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Fixed v;
 
   if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
@@ -256,6 +327,7 @@
                           void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -274,23 +346,6 @@
   return true;
 }
 
-static hb_position_t
-hb_ft_get_glyph_h_kerning (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t left_glyph,
-                           hb_codepoint_t right_glyph,
-                           void *user_data HB_UNUSED)
-{
-  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-  FT_Vector kerningv;
-
-  FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
-  if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
-    return 0;
-
-  return kerningv.x;
-}
-
 static hb_bool_t
 hb_ft_get_glyph_extents (hb_font_t *font,
                          void *font_data,
@@ -299,6 +354,7 @@
                          void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -331,6 +387,7 @@
                                void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
@@ -356,8 +413,10 @@
                       void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
+  FT_Face ft_face = ft_font->ft_face;
 
-  hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size);
+  hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size);
   if (ret && (size && !*name))
     ret = false;
 
@@ -372,6 +431,7 @@
                            void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
 
   if (len < 0)
@@ -404,10 +464,11 @@
                           void *user_data HB_UNUSED)
 {
   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+  hb_lock_t lock (ft_font->lock);
   FT_Face ft_face = ft_font->ft_face;
-  metrics->ascender = ft_face->size->metrics.ascender;
-  metrics->descender = ft_face->size->metrics.descender;
-  metrics->line_gap = ft_face->size->metrics.height - (ft_face->size->metrics.ascender - ft_face->size->metrics.descender);
+  metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
+  metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
+  metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
   if (font->y_scale < 0)
   {
     metrics->ascender = -metrics->ascender;
@@ -417,41 +478,25 @@
   return true;
 }
 
-static hb_font_funcs_t *static_ft_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ft_funcs (void)
-{
-retry:
-  hb_font_funcs_t *ft_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, ft_funcs, nullptr))
-    goto retry;
-
-  hb_font_funcs_destroy (ft_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_ft_funcs ();
 #endif
 
-static void
-_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
+static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
 {
-retry:
-  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
-
-  if (unlikely (!funcs))
+  static hb_font_funcs_t *create ()
   {
-    funcs = hb_font_funcs_create ();
+    hb_font_funcs_t *funcs = hb_font_funcs_create ();
 
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ft_get_font_h_extents, nullptr, nullptr);
     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
+    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr);
+    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
     hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
@@ -459,20 +504,35 @@
 
     hb_font_funcs_make_immutable (funcs);
 
-    if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, nullptr, funcs)) {
-      hb_font_funcs_destroy (funcs);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_ft_funcs);
+#endif
+
+    return funcs;
+  }
+} static_ft_funcs;
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_ft_funcs ()
+{
+  static_ft_funcs.free_instance ();
+}
 #endif
-  };
 
+static hb_font_funcs_t *
+_hb_ft_get_font_funcs ()
+{
+  return static_ft_funcs.get_unconst ();
+}
+
+static void
+_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
+{
   bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
 
   hb_font_set_funcs (font,
-                     funcs,
+                     _hb_ft_get_font_funcs (),
                      _hb_ft_font_create (ft_face, symbol, unref),
                      _hb_ft_font_destroy);
 }
@@ -497,7 +557,8 @@
     return nullptr;
 
   error = FT_Load_Sfnt_Table (ft_face, tag, 0, buffer, &length);
-  if (error) {
+  if (error)
+  {
     free (buffer);
     return nullptr;
   }
@@ -683,47 +744,47 @@
   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
 }
 
+#if HB_USE_ATEXIT
+static void free_static_ft_library ();
+#endif
 
-/* Thread-safe, lock-free, FT_Library */
+static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (FT_Library),
+                                                             hb_ft_library_lazy_loader_t>
+{
+  static FT_Library create ()
+  {
+    FT_Library l;
+    if (FT_Init_FreeType (&l))
+      return nullptr;
 
-static FT_Library ft_library;
+#if HB_USE_ATEXIT
+    atexit (free_static_ft_library);
+#endif
 
-#ifdef HB_USE_ATEXIT
+    return l;
+  }
+  static void destroy (FT_Library l)
+  {
+    FT_Done_FreeType (l);
+  }
+  static FT_Library get_null ()
+  {
+    return nullptr;
+  }
+} static_ft_library;
+
+#if HB_USE_ATEXIT
 static
-void free_ft_library (void)
+void free_static_ft_library ()
 {
-retry:
-  FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
-  if (!hb_atomic_ptr_cmpexch (&ft_library, library, nullptr))
-    goto retry;
-
-  FT_Done_FreeType (library);
+  static_ft_library.free_instance ();
 }
 #endif
 
 static FT_Library
-get_ft_library (void)
+get_ft_library ()
 {
-retry:
-  FT_Library library = (FT_Library) hb_atomic_ptr_get (&ft_library);
-
-  if (unlikely (!library))
-  {
-    /* Not found; allocate one. */
-    if (FT_Init_FreeType (&library))
-      return nullptr;
-
-    if (!hb_atomic_ptr_cmpexch (&ft_library, nullptr, library)) {
-      FT_Done_FreeType (library);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_ft_library); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return library;
+  return static_ft_library.get_unconst ();
 }
 
 static void
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-iter.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_ITER_HH
+#define HB_ITER_HH
+
+#include "hb.hh"
+#include "hb-null.hh"
+
+
+/* Unified iterator object.
+ *
+ * The goal of this template is to make the same iterator interface
+ * available to all types, and make it very easy and compact to use.
+ * hb_iter_tator objects are small, light-weight, objects that can be
+ * copied by value.  If the collection / object being iterated on
+ * is writable, then the iterator returns lvalues, otherwise it
+ * returns rvalues.
+ */
+
+/* Base class for all iterators. */
+template <typename Iter, typename Item = typename Iter::__item_type__>
+struct hb_iter_t
+{
+  typedef Iter iter_t;
+  typedef iter_t const_iter_t;
+  typedef Item item_t;
+  static constexpr unsigned item_size = hb_static_size (Item);
+
+  private:
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
+        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
+  public:
+
+  /* Operators. */
+  operator iter_t () { return iter(); }
+  explicit_operator bool () const { return more (); }
+  item_t& operator * () const { return item (); }
+  item_t& operator [] (signed i) const { return item_at ((unsigned) i); }
+  iter_t& operator += (unsigned count) { forward (count); return *thiz(); }
+  iter_t& operator ++ () { next (); return *thiz(); }
+  iter_t& operator -= (unsigned count) { rewind (count); return *thiz(); }
+  iter_t& operator -- () { prev (); return *thiz(); }
+  iter_t operator + (unsigned count) { iter_t c (*thiz()); c += count; return c; }
+  iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
+  iter_t operator - (unsigned count) { iter_t c (*thiz()); c -= count; return c; }
+  iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
+
+  /* Methods. */
+  iter_t iter () const { return *thiz(); }
+  const_iter_t const_iter () const { return iter (); }
+  item_t& item () const { return thiz()->__item__ (); }
+  item_t& item_at (unsigned i) const { return thiz()->__item_at__ (i); }
+  bool more () const { return thiz()->__more__ (); }
+  unsigned len () const { return thiz()->__len__ (); }
+  void next () { thiz()->__next__ (); }
+  void forward (unsigned n) { thiz()->__forward__ (n); }
+  void prev () { thiz()->__prev__ (); }
+  void rewind (unsigned n) { thiz()->__rewind__ (n); }
+  bool random_access () const { return thiz()->__random_access__ (); }
+
+  protected:
+  hb_iter_t () {}
+  hb_iter_t (const hb_iter_t &o HB_UNUSED) {}
+  void operator = (const hb_iter_t &o HB_UNUSED) {}
+};
+
+/* Base class for sorted iterators.  Does not enforce anything.
+ * Just for class taxonomy and requirements. */
+template <typename Iter, typename Item = typename Iter::__item_type__>
+struct hb_sorted_iter_t : hb_iter_t<Iter, Item>
+{
+  protected:
+  hb_sorted_iter_t () {}
+  hb_sorted_iter_t (const hb_sorted_iter_t &o) : hb_iter_t<Iter, Item> (o) {}
+  void operator = (const hb_sorted_iter_t &o HB_UNUSED) {}
+};
+
+/* Mixin to fill in what the subclass doesn't provide. */
+template <typename iter_t, typename item_t = typename iter_t::__item_type__>
+struct hb_iter_mixin_t
+{
+  private:
+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
+  const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
+        iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
+  public:
+
+  /* Access: Implement __item__(), or __item_at__() if random-access. */
+  item_t& __item__ () const { return thiz()->item_at (0); }
+  item_t& __item_at__ (unsigned i) const { return *(thiz() + i); }
+
+  /* Termination: Implement __more__(), or __len__() if random-access. */
+  bool __more__ () const { return thiz()->__len__ (); }
+  unsigned __len__ () const
+  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
+
+  /* Advancing: Implement __next__(), or __forward__() if random-access. */
+  void __next__ () { thiz()->forward (1); }
+  void __forward__ (unsigned n) { while (n--) thiz()->next (); }
+
+  /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
+  void __prev__ () { thiz()->rewind (1); }
+  void __rewind__ (unsigned n) { while (n--) thiz()->prev (); }
+
+  /* Random access: Return true if item_at(), len(), forward() are fast. */
+  bool __random_access__ () const { return false; }
+};
+
+
+/* Functions operating on iterators or iteratables. */
+
+template <typename C, typename V> inline void
+hb_fill (const C& c, const V &v)
+{
+  for (typename C::iter_t i (c); i; i++)
+    hb_assign (*i, v);
+}
+
+template <typename S, typename D> inline bool
+hb_copy (hb_iter_t<D> &id, hb_iter_t<S> &is)
+{
+  for (; id && is; ++id, ++is)
+    *id = *is;
+  return !is;
+}
+
+
+#endif /* HB_ITER_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-kern.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_KERN_HH
+#define HB_KERN_HH
+
+#include "hb-open-type.hh"
+#include "hb-aat-layout-common.hh"
+#include "hb-ot-layout-gpos-table.hh"
+
+
+namespace OT {
+
+
+template <typename Driver>
+struct hb_kern_machine_t
+{
+  hb_kern_machine_t (const Driver &driver_,
+                     bool crossStream_ = false) :
+                       driver (driver_),
+                       crossStream (crossStream_) {}
+
+  HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW
+  void kern (hb_font_t   *font,
+             hb_buffer_t *buffer,
+             hb_mask_t    kern_mask,
+             bool         scale = true) const
+  {
+    OT::hb_ot_apply_context_t c (1, font, buffer);
+    c.set_lookup_mask (kern_mask);
+    c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
+    OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
+    skippy_iter.init (&c);
+
+    bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
+    unsigned int count = buffer->len;
+    hb_glyph_info_t *info = buffer->info;
+    hb_glyph_position_t *pos = buffer->pos;
+    for (unsigned int idx = 0; idx < count;)
+    {
+      if (!(info[idx].mask & kern_mask))
+      {
+        idx++;
+        continue;
+      }
+
+      skippy_iter.reset (idx, 1);
+      if (!skippy_iter.next ())
+      {
+        idx++;
+        continue;
+      }
+
+      unsigned int i = idx;
+      unsigned int j = skippy_iter.idx;
+
+      hb_position_t kern = driver.get_kerning (info[i].codepoint,
+                                               info[j].codepoint);
+
+
+      if (likely (!kern))
+        goto skip;
+
+      if (horizontal)
+      {
+        if (scale)
+          kern = font->em_scale_x (kern);
+        if (crossStream)
+        {
+          pos[j].y_offset = kern;
+          buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+        }
+        else
+        {
+          hb_position_t kern1 = kern >> 1;
+          hb_position_t kern2 = kern - kern1;
+          pos[i].x_advance += kern1;
+          pos[j].x_advance += kern2;
+          pos[j].x_offset += kern2;
+        }
+      }
+      else
+      {
+        if (scale)
+          kern = font->em_scale_y (kern);
+        if (crossStream)
+        {
+          pos[j].x_offset = kern;
+          buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+        }
+        else
+        {
+          hb_position_t kern1 = kern >> 1;
+          hb_position_t kern2 = kern - kern1;
+          pos[i].y_advance += kern1;
+          pos[j].y_advance += kern2;
+          pos[j].y_offset += kern2;
+        }
+      }
+
+      buffer->unsafe_to_break (i, j + 1);
+
+    skip:
+      idx = skippy_iter.idx;
+    }
+  }
+
+  const Driver &driver;
+  bool crossStream;
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_KERN_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-machinery.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,931 @@
+/*
+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
+ * Copyright © 2012,2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MACHINERY_HH
+#define HB_MACHINERY_HH
+
+#include "hb.hh"
+#include "hb-blob.hh"
+
+#include "hb-array.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * Casts
+ */
+
+/* Cast to struct T, reference to reference */
+template<typename Type, typename TObject>
+static inline const Type& CastR(const TObject &X)
+{ return reinterpret_cast<const Type&> (X); }
+template<typename Type, typename TObject>
+static inline Type& CastR(TObject &X)
+{ return reinterpret_cast<Type&> (X); }
+
+/* Cast to struct T, pointer to pointer */
+template<typename Type, typename TObject>
+static inline const Type* CastP(const TObject *X)
+{ return reinterpret_cast<const Type*> (X); }
+template<typename Type, typename TObject>
+static inline Type* CastP(TObject *X)
+{ return reinterpret_cast<Type*> (X); }
+
+/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
+ * location pointed to by P plus Ofs bytes. */
+template<typename Type>
+static inline const Type& StructAtOffset(const void *P, unsigned int offset)
+{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
+template<typename Type>
+static inline Type& StructAtOffset(void *P, unsigned int offset)
+{ return * reinterpret_cast<Type*> ((char *) P + offset); }
+template<typename Type>
+static inline const Type& StructAtOffsetUnaligned(const void *P, unsigned int offset)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  return * reinterpret_cast<Type*> ((char *) P + offset);
+#pragma GCC diagnostic pop
+}
+template<typename Type>
+static inline Type& StructAtOffsetUnaligned(void *P, unsigned int offset)
+{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-align"
+  return * reinterpret_cast<Type*> ((char *) P + offset);
+#pragma GCC diagnostic pop
+}
+
+/* StructAfter<T>(X) returns the struct T& that is placed after X.
+ * Works with X of variable size also.  X must implement get_size() */
+template<typename Type, typename TObject>
+static inline const Type& StructAfter(const TObject &X)
+{ return StructAtOffset<Type>(&X, X.get_size()); }
+template<typename Type, typename TObject>
+static inline Type& StructAfter(TObject &X)
+{ return StructAtOffset<Type>(&X, X.get_size()); }
+
+
+/*
+ * Size checking
+ */
+
+/* Check _assertion in a method environment */
+#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
+  void _instance_assertion_on_line_##_line () const \
+  { static_assert ((_assertion), ""); }
+# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
+# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
+
+/* Check that _code compiles in a method environment */
+#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
+  void _compiles_assertion_on_line_##_line () const \
+  { _code; }
+# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
+# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
+
+
+#define DEFINE_SIZE_STATIC(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)) \
+  unsigned int get_size () const { return (size); } \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size); \
+  static constexpr unsigned static_size = (size)
+
+#define DEFINE_SIZE_UNION(size, _member) \
+  DEFINE_COMPILES_ASSERTION ((void) this->u._member.static_size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof(this->u._member) == (size)) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_MIN(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_UNBOUNDED(size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)) \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_ARRAY(size, array) \
+  DEFINE_COMPILES_ASSERTION ((void) (array)[0].static_size) \
+  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof ((array)[0])) \
+  static constexpr unsigned null_size = (size); \
+  static constexpr unsigned min_size = (size)
+
+#define DEFINE_SIZE_ARRAY_SIZED(size, array) \
+  unsigned int get_size () const { return (size - (array).min_size + (array).get_size ()); } \
+  DEFINE_SIZE_ARRAY(size, array)
+
+
+/*
+ * Dispatch
+ */
+
+template <typename Context, typename Return, unsigned int MaxDebugDepth>
+struct hb_dispatch_context_t
+{
+  static constexpr unsigned max_debug_depth = MaxDebugDepth;
+  typedef Return return_t;
+  template <typename T, typename F>
+  bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
+  static return_t no_dispatch_return_value () { return Context::default_return_value (); }
+  static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
+};
+
+
+/*
+ * Sanitize
+ *
+ *
+ * === Introduction ===
+ *
+ * The sanitize machinery is at the core of our zero-cost font loading.  We
+ * mmap() font file into memory and create a blob out of it.  Font subtables
+ * are returned as a readonly sub-blob of the main font blob.  These table
+ * blobs are then sanitized before use, to ensure invalid memory access does
+ * not happen.  The toplevel sanitize API use is like, eg. to load the 'head'
+ * table:
+ *
+ *   hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<OT::head> (face);
+ *
+ * The blob then can be converted to a head table struct with:
+ *
+ *   const head *head_table = head_blob->as<head> ();
+ *
+ * What the reference_table does is, to call hb_face_reference_table() to load
+ * the table blob, sanitize it and return either the sanitized blob, or empty
+ * blob if sanitization failed.  The blob->as() function returns the null
+ * object of its template type argument if the blob is empty.  Otherwise, it
+ * just casts the blob contents to the desired type.
+ *
+ * Sanitizing a blob of data with a type T works as follows (with minor
+ * simplification):
+ *
+ *   - Cast blob content to T*, call sanitize() method of it,
+ *   - If sanitize succeeded, return blob.
+ *   - Otherwise, if blob is not writable, try making it writable,
+ *     or copy if cannot be made writable in-place,
+ *   - Call sanitize() again.  Return blob if sanitize succeeded.
+ *   - Return empty blob otherwise.
+ *
+ *
+ * === The sanitize() contract ===
+ *
+ * The sanitize() method of each object type shall return true if it's safe to
+ * call other methods of the object, and false otherwise.
+ *
+ * Note that what sanitize() checks for might align with what the specification
+ * describes as valid table data, but does not have to be.  In particular, we
+ * do NOT want to be pedantic and concern ourselves with validity checks that
+ * are irrelevant to our use of the table.  On the contrary, we want to be
+ * lenient with error handling and accept invalid data to the extent that it
+ * does not impose extra burden on us.
+ *
+ * Based on the sanitize contract, one can see that what we check for depends
+ * on how we use the data in other table methods.  Ie. if other table methods
+ * assume that offsets do NOT point out of the table data block, then that's
+ * something sanitize() must check for (GSUB/GPOS/GDEF/etc work this way).  On
+ * the other hand, if other methods do such checks themselves, then sanitize()
+ * does not have to bother with them (glyf/local work this way).  The choice
+ * depends on the table structure and sanitize() performance.  For example, to
+ * check glyf/loca offsets in sanitize() would cost O(num-glyphs).  We try hard
+ * to avoid such costs during font loading.  By postponing such checks to the
+ * actual glyph loading, we reduce the sanitize cost to O(1) and total runtime
+ * cost to O(used-glyphs).  As such, this is preferred.
+ *
+ * The same argument can be made re GSUB/GPOS/GDEF, but there, the table
+ * structure is so complicated that by checking all offsets at sanitize() time,
+ * we make the code much simpler in other methods, as offsets and referenced
+ * objects do not need to be validated at each use site.
+ */
+
+/* This limits sanitizing time on really broken fonts. */
+#ifndef HB_SANITIZE_MAX_EDITS
+#define HB_SANITIZE_MAX_EDITS 32
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_FACTOR
+#define HB_SANITIZE_MAX_OPS_FACTOR 8
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_MIN
+#define HB_SANITIZE_MAX_OPS_MIN 16384
+#endif
+#ifndef HB_SANITIZE_MAX_OPS_MAX
+#define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF
+#endif
+
+struct hb_sanitize_context_t :
+       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
+{
+  hb_sanitize_context_t () :
+        debug_depth (0),
+        start (nullptr), end (nullptr),
+        max_ops (0),
+        writable (false), edit_count (0),
+        blob (nullptr),
+        num_glyphs (65536),
+        num_glyphs_set (false) {}
+
+  const char *get_name () { return "SANITIZE"; }
+  template <typename T, typename F>
+  bool may_dispatch (const T *obj HB_UNUSED, const F *format)
+  { return format->sanitize (this); }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.sanitize (this); }
+  static return_t default_return_value () { return true; }
+  static return_t no_dispatch_return_value () { return false; }
+  bool stop_sublookup_iteration (const return_t r) const { return !r; }
+
+  void init (hb_blob_t *b)
+  {
+    this->blob = hb_blob_reference (b);
+    this->writable = false;
+  }
+
+  void set_num_glyphs (unsigned int num_glyphs_)
+  {
+    num_glyphs = num_glyphs_;
+    num_glyphs_set = true;
+  }
+  unsigned int get_num_glyphs () { return num_glyphs; }
+
+  void set_max_ops (int max_ops_) { max_ops = max_ops_; }
+
+  template <typename T>
+  void set_object (const T *obj)
+  {
+    reset_object ();
+
+    if (!obj) return;
+
+    const char *obj_start = (const char *) obj;
+    if (unlikely (obj_start < this->start || this->end <= obj_start))
+      this->start = this->end = nullptr;
+    else
+    {
+      this->start = obj_start;
+      this->end   = obj_start + MIN<uintptr_t> (this->end - obj_start, obj->get_size ());
+    }
+  }
+
+  void reset_object ()
+  {
+    this->start = this->blob->data;
+    this->end = this->start + this->blob->length;
+    assert (this->start <= this->end); /* Must not overflow. */
+  }
+
+  void start_processing ()
+  {
+    reset_object ();
+    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+                         (unsigned) HB_SANITIZE_MAX_OPS_MIN);
+    this->edit_count = 0;
+    this->debug_depth = 0;
+
+    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
+                     "start [%p..%p] (%lu bytes)",
+                     this->start, this->end,
+                     (unsigned long) (this->end - this->start));
+  }
+
+  void end_processing ()
+  {
+    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
+                     "end [%p..%p] %u edit requests",
+                     this->start, this->end, this->edit_count);
+
+    hb_blob_destroy (this->blob);
+    this->blob = nullptr;
+    this->start = this->end = nullptr;
+  }
+
+  bool check_range (const void *base,
+                           unsigned int len) const
+  {
+    const char *p = (const char *) base;
+    bool ok = this->start <= p &&
+              p <= this->end &&
+              (unsigned int) (this->end - p) >= len &&
+              this->max_ops-- > 0;
+
+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+       "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
+       p, p + len, len,
+       this->start, this->end,
+       ok ? "OK" : "OUT-OF-RANGE");
+
+    return likely (ok);
+  }
+
+  template <typename T>
+  bool check_range (const T *base,
+                           unsigned int a,
+                           unsigned int b) const
+  {
+    return !hb_unsigned_mul_overflows (a, b) &&
+           this->check_range (base, a * b);
+  }
+
+  template <typename T>
+  bool check_range (const T *base,
+                           unsigned int a,
+                           unsigned int b,
+                           unsigned int c) const
+  {
+    return !hb_unsigned_mul_overflows (a, b) &&
+           this->check_range (base, a * b, c);
+  }
+
+  template <typename T>
+  bool check_array (const T *base, unsigned int len) const
+  {
+    return this->check_range (base, len, hb_static_size (T));
+  }
+
+  template <typename T>
+  bool check_array (const T *base,
+                    unsigned int a,
+                    unsigned int b) const
+  {
+    return this->check_range (base, a, b, hb_static_size (T));
+  }
+
+  template <typename Type>
+  bool check_struct (const Type *obj) const
+  { return likely (this->check_range (obj, obj->min_size)); }
+
+  bool may_edit (const void *base, unsigned int len)
+  {
+    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
+      return false;
+
+    const char *p = (const char *) base;
+    this->edit_count++;
+
+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
+       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
+       this->edit_count,
+       p, p + len, len,
+       this->start, this->end,
+       this->writable ? "GRANTED" : "DENIED");
+
+    return this->writable;
+  }
+
+  template <typename Type, typename ValueType>
+  bool try_set (const Type *obj, const ValueType &v)
+  {
+    if (this->may_edit (obj, hb_static_size (Type)))
+    {
+      hb_assign (* const_cast<Type *> (obj), v);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename Type>
+  hb_blob_t *sanitize_blob (hb_blob_t *blob)
+  {
+    bool sane;
+
+    init (blob);
+
+  retry:
+    DEBUG_MSG_FUNC (SANITIZE, start, "start");
+
+    start_processing ();
+
+    if (unlikely (!start))
+    {
+      end_processing ();
+      return blob;
+    }
+
+    Type *t = CastP<Type> (const_cast<char *> (start));
+
+    sane = t->sanitize (this);
+    if (sane)
+    {
+      if (edit_count)
+      {
+        DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
+
+        /* sanitize again to ensure no toe-stepping */
+        edit_count = 0;
+        sane = t->sanitize (this);
+        if (edit_count) {
+          DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
+          sane = false;
+        }
+      }
+    }
+    else
+    {
+      if (edit_count && !writable) {
+        start = hb_blob_get_data_writable (blob, nullptr);
+        end = start + blob->length;
+
+        if (start)
+        {
+          writable = true;
+          /* ok, we made it writable by relocating.  try again */
+          DEBUG_MSG_FUNC (SANITIZE, start, "retry");
+          goto retry;
+        }
+      }
+    }
+
+    end_processing ();
+
+    DEBUG_MSG_FUNC (SANITIZE, start, sane ? "PASSED" : "FAILED");
+    if (sane)
+    {
+      hb_blob_make_immutable (blob);
+      return blob;
+    }
+    else
+    {
+      hb_blob_destroy (blob);
+      return hb_blob_get_empty ();
+    }
+  }
+
+  template <typename Type>
+  hb_blob_t *reference_table (const hb_face_t *face, hb_tag_t tableTag = Type::tableTag)
+  {
+    if (!num_glyphs_set)
+      set_num_glyphs (hb_face_get_glyph_count (face));
+    return sanitize_blob<Type> (hb_face_reference_table (face, tableTag));
+  }
+
+  mutable unsigned int debug_depth;
+  const char *start, *end;
+  mutable int max_ops;
+  private:
+  bool writable;
+  unsigned int edit_count;
+  hb_blob_t *blob;
+  unsigned int num_glyphs;
+  bool  num_glyphs_set;
+};
+
+struct hb_sanitize_with_object_t
+{
+  template <typename T>
+  hb_sanitize_with_object_t (hb_sanitize_context_t *c,
+                                    const T& obj) : c (c)
+  { c->set_object (obj); }
+  ~hb_sanitize_with_object_t ()
+  { c->reset_object (); }
+
+  private:
+  hb_sanitize_context_t *c;
+};
+
+
+/*
+ * Serialize
+ */
+
+struct hb_serialize_context_t
+{
+  hb_serialize_context_t (void *start_, unsigned int size)
+  {
+    this->start = (char *) start_;
+    this->end = this->start + size;
+    reset ();
+  }
+
+  bool in_error () const { return !this->successful; }
+
+  void reset ()
+  {
+    this->successful = true;
+    this->head = this->start;
+    this->debug_depth = 0;
+  }
+
+  bool propagate_error (bool e)
+  { return this->successful = this->successful && e; }
+  template <typename T> bool propagate_error (const T &obj)
+  { return this->successful = this->successful && !obj.in_error (); }
+  template <typename T> bool propagate_error (const T *obj)
+  { return this->successful = this->successful && !obj->in_error (); }
+  template <typename T1, typename T2> bool propagate_error (T1 &o1, T2 &o2)
+  { return propagate_error (o1) && propagate_error (o2); }
+  template <typename T1, typename T2> bool propagate_error (T1 *o1, T2 *o2)
+  { return propagate_error (o1) && propagate_error (o2); }
+  template <typename T1, typename T2, typename T3>
+  bool propagate_error (T1 &o1, T2 &o2, T3 &o3)
+  { return propagate_error (o1) && propagate_error (o2, o3); }
+  template <typename T1, typename T2, typename T3>
+  bool propagate_error (T1 *o1, T2 *o2, T3 *o3)
+  { return propagate_error (o1) && propagate_error (o2, o3); }
+
+  /* To be called around main operation. */
+  template <typename Type>
+  Type *start_serialize ()
+  {
+    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
+                     "start [%p..%p] (%lu bytes)",
+                     this->start, this->end,
+                     (unsigned long) (this->end - this->start));
+
+    return start_embed<Type> ();
+  }
+  void end_serialize ()
+  {
+    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
+                     "end [%p..%p] serialized %d bytes; %s",
+                     this->start, this->end,
+                     (int) (this->head - this->start),
+                     this->successful ? "successful" : "UNSUCCESSFUL");
+  }
+
+  unsigned int length () const { return this->head - this->start; }
+
+  void align (unsigned int alignment)
+  {
+    unsigned int l = length () % alignment;
+    if (l)
+      allocate_size<void> (alignment - l);
+  }
+
+  template <typename Type>
+  Type *start_embed (const Type *_ HB_UNUSED = nullptr) const
+  {
+    Type *ret = reinterpret_cast<Type *> (this->head);
+    return ret;
+  }
+
+  template <typename Type>
+  Type *allocate_size (unsigned int size)
+  {
+    if (unlikely (!this->successful || this->end - this->head < ptrdiff_t (size))) {
+      this->successful = false;
+      return nullptr;
+    }
+    memset (this->head, 0, size);
+    char *ret = this->head;
+    this->head += size;
+    return reinterpret_cast<Type *> (ret);
+  }
+
+  template <typename Type>
+  Type *allocate_min ()
+  {
+    return this->allocate_size<Type> (Type::min_size);
+  }
+
+  template <typename Type>
+  Type *embed (const Type &obj)
+  {
+    unsigned int size = obj.get_size ();
+    Type *ret = this->allocate_size<Type> (size);
+    if (unlikely (!ret)) return nullptr;
+    memcpy (ret, &obj, size);
+    return ret;
+  }
+  template <typename Type>
+  hb_serialize_context_t &operator << (const Type &obj) { embed (obj); return *this; }
+
+  template <typename Type>
+  Type *extend_size (Type &obj, unsigned int size)
+  {
+    assert (this->start <= (char *) &obj);
+    assert ((char *) &obj <= this->head);
+    assert ((char *) &obj + size >= this->head);
+    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
+    return reinterpret_cast<Type *> (&obj);
+  }
+
+  template <typename Type>
+  Type *extend_min (Type &obj) { return extend_size (obj, obj.min_size); }
+
+  template <typename Type>
+  Type *extend (Type &obj) { return extend_size (obj, obj.get_size ()); }
+
+  /* Output routines. */
+  template <typename Type>
+  Type *copy () const
+  {
+    assert (this->successful);
+    unsigned int len = this->head - this->start;
+    void *p = malloc (len);
+    if (p)
+      memcpy (p, this->start, len);
+    return reinterpret_cast<Type *> (p);
+  }
+  hb_bytes_t copy_bytes () const
+  {
+    assert (this->successful);
+    unsigned int len = this->head - this->start;
+    void *p = malloc (len);
+    if (p)
+      memcpy (p, this->start, len);
+    else
+      return hb_bytes_t ();
+    return hb_bytes_t ((char *) p, len);
+  }
+  hb_blob_t *copy_blob () const
+  {
+    assert (this->successful);
+    return hb_blob_create (this->start,
+                           this->head - this->start,
+                           HB_MEMORY_MODE_DUPLICATE,
+                           nullptr, nullptr);
+  }
+
+  public:
+  unsigned int debug_depth;
+  char *start, *end, *head;
+  bool successful;
+};
+
+
+
+/*
+ * Big-endian integers.
+ */
+
+template <typename Type, int Bytes> struct BEInt;
+
+template <typename Type>
+struct BEInt<Type, 1>
+{
+  public:
+  void set (Type V)      { v = V; }
+  operator Type () const { return v; }
+  private: uint8_t v;
+};
+template <typename Type>
+struct BEInt<Type, 2>
+{
+  public:
+  void set (Type V)
+  {
+    v[0] = (V >>  8) & 0xFF;
+    v[1] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+    defined(__BYTE_ORDER) && \
+    (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+    /* Spoon-feed the compiler a big-endian integer with alignment 1.
+     * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+    struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+    return __builtin_bswap16 (((packed_uint16_t *) this)->v);
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+    return ((packed_uint16_t *) this)->v;
+#endif
+#endif
+    return (v[0] <<  8)
+         + (v[1]      );
+  }
+  private: uint8_t v[2];
+};
+template <typename Type>
+struct BEInt<Type, 3>
+{
+  public:
+  void set (Type V)
+  {
+    v[0] = (V >> 16) & 0xFF;
+    v[1] = (V >>  8) & 0xFF;
+    v[2] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+    return (v[0] << 16)
+         + (v[1] <<  8)
+         + (v[2]      );
+  }
+  private: uint8_t v[3];
+};
+template <typename Type>
+struct BEInt<Type, 4>
+{
+  public:
+  typedef Type type;
+  void set (Type V)
+  {
+    v[0] = (V >> 24) & 0xFF;
+    v[1] = (V >> 16) & 0xFF;
+    v[2] = (V >>  8) & 0xFF;
+    v[3] = (V      ) & 0xFF;
+  }
+  operator Type () const
+  {
+    return (v[0] << 24)
+         + (v[1] << 16)
+         + (v[2] <<  8)
+         + (v[3]      );
+  }
+  private: uint8_t v[4];
+};
+
+
+/*
+ * Lazy loaders.
+ */
+
+template <typename Data, unsigned int WheresData>
+struct hb_data_wrapper_t
+{
+  static_assert (WheresData > 0, "");
+
+  Data * get_data () const
+  { return *(((Data **) (void *) this) - WheresData); }
+
+  bool is_inert () const { return !get_data (); }
+
+  template <typename Stored, typename Subclass>
+  Stored * call_create () const { return Subclass::create (get_data ()); }
+};
+template <>
+struct hb_data_wrapper_t<void, 0>
+{
+  bool is_inert () const { return false; }
+
+  template <typename Stored, typename Funcs>
+  Stored * call_create () const { return Funcs::create (); }
+};
+
+template <typename T1, typename T2> struct hb_non_void_t { typedef T1 value; };
+template <typename T2> struct hb_non_void_t<void, T2> { typedef T2 value; };
+
+template <typename Returned,
+          typename Subclass = void,
+          typename Data = void,
+          unsigned int WheresData = 0,
+          typename Stored = Returned>
+struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
+{
+  typedef typename hb_non_void_t<Subclass,
+                                 hb_lazy_loader_t<Returned,Subclass,Data,WheresData,Stored>
+                                >::value Funcs;
+
+  void init0 () {} /* Init, when memory is already set to 0. No-op for us. */
+  void init ()  { instance.set_relaxed (nullptr); }
+  void fini ()  { do_destroy (instance.get ()); }
+
+  void free_instance ()
+  {
+  retry:
+    Stored *p = instance.get ();
+    if (unlikely (p && !cmpexch (p, nullptr)))
+      goto retry;
+    do_destroy (p);
+  }
+
+  static void do_destroy (Stored *p)
+  {
+    if (p && p != const_cast<Stored *> (Funcs::get_null ()))
+      Funcs::destroy (p);
+  }
+
+  const Returned * operator -> () const { return get (); }
+  const Returned & operator * () const  { return *get (); }
+  explicit_operator bool () const
+  { return get_stored () != Funcs::get_null (); }
+  template <typename C> operator const C * () const { return get (); }
+
+  Stored * get_stored () const
+  {
+  retry:
+    Stored *p = this->instance.get ();
+    if (unlikely (!p))
+    {
+      if (unlikely (this->is_inert ()))
+        return const_cast<Stored *> (Funcs::get_null ());
+
+      p = this->template call_create<Stored, Funcs> ();
+      if (unlikely (!p))
+        p = const_cast<Stored *> (Funcs::get_null ());
+
+      if (unlikely (!cmpexch (nullptr, p)))
+      {
+        do_destroy (p);
+        goto retry;
+      }
+    }
+    return p;
+  }
+  Stored * get_stored_relaxed () const
+  {
+    return this->instance.get_relaxed ();
+  }
+
+  bool cmpexch (Stored *current, Stored *value) const
+  {
+    /* This *must* be called when there are no other threads accessing. */
+    return this->instance.cmpexch (current, value);
+  }
+
+  const Returned * get () const { return Funcs::convert (get_stored ()); }
+  const Returned * get_relaxed () const { return Funcs::convert (get_stored_relaxed ()); }
+  Returned * get_unconst () const { return const_cast<Returned *> (Funcs::convert (get_stored ())); }
+
+  /* To be possibly overloaded by subclasses. */
+  static Returned* convert (Stored *p) { return p; }
+
+  /* By default null/init/fini the object. */
+  static const Stored* get_null () { return &Null(Stored); }
+  static Stored *create (Data *data)
+  {
+    Stored *p = (Stored *) calloc (1, sizeof (Stored));
+    if (likely (p))
+      p->init (data);
+    return p;
+  }
+  static Stored *create ()
+  {
+    Stored *p = (Stored *) calloc (1, sizeof (Stored));
+    if (likely (p))
+      p->init ();
+    return p;
+  }
+  static void destroy (Stored *p)
+  {
+    p->fini ();
+    free (p);
+  }
+
+//  private:
+  /* Must only have one pointer. */
+  hb_atomic_ptr_t<Stored *> instance;
+};
+
+/* Specializations. */
+
+template <typename T, unsigned int WheresFace>
+struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
+                                                hb_face_lazy_loader_t<T, WheresFace>,
+                                                hb_face_t, WheresFace> {};
+
+template <typename T, unsigned int WheresFace>
+struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
+                                                 hb_table_lazy_loader_t<T, WheresFace>,
+                                                 hb_face_t, WheresFace,
+                                                 hb_blob_t>
+{
+  static hb_blob_t *create (hb_face_t *face)
+  { return hb_sanitize_context_t ().reference_table<T> (face); }
+  static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
+
+  static const hb_blob_t *get_null ()
+  { return hb_blob_get_empty (); }
+
+  static const T* convert (const hb_blob_t *blob)
+  { return blob->as<T> (); }
+
+  hb_blob_t* get_blob () const { return this->get_stored (); }
+};
+
+template <typename Subclass>
+struct hb_font_funcs_lazy_loader_t : hb_lazy_loader_t<hb_font_funcs_t, Subclass>
+{
+  static void destroy (hb_font_funcs_t *p)
+  { hb_font_funcs_destroy (p); }
+  static const hb_font_funcs_t *get_null ()
+  { return hb_font_funcs_get_empty (); }
+};
+template <typename Subclass>
+struct hb_unicode_funcs_lazy_loader_t : hb_lazy_loader_t<hb_unicode_funcs_t, Subclass>
+{
+  static void destroy (hb_unicode_funcs_t *p)
+  { hb_unicode_funcs_destroy (p); }
+  static const hb_unicode_funcs_t *get_null ()
+  { return hb_unicode_funcs_get_empty (); }
+};
+
+
+#endif /* HB_MACHINERY_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,255 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_MAP_PRIVATE_HH
-#define HB_MAP_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-template <typename T>
-inline uint32_t Hash (const T &v)
-{
-  /* Knuth's multiplicative method: */
-  return (uint32_t) v * 2654435761u;
-}
-
-
-/*
- * hb_map_t
- */
-
-struct hb_map_t
-{
-  struct item_t
-  {
-    hb_codepoint_t key;
-    hb_codepoint_t value;
-
-    inline bool is_unused (void) const { return key == INVALID; }
-    inline bool is_tombstone (void) const { return key != INVALID && value == INVALID; }
-  };
-
-  hb_object_header_t header;
-  bool successful; /* Allocations successful */
-  unsigned int population; /* Not including tombstones. */
-  unsigned int occupancy; /* Including tombstones. */
-  unsigned int mask;
-  unsigned int prime;
-  item_t *items;
-
-  inline void init_shallow (void)
-  {
-    successful = true;
-    population = occupancy = 0;
-    mask = 0;
-    prime = 0;
-    items = nullptr;
-  }
-  inline void init (void)
-  {
-    hb_object_init (this);
-    init_shallow ();
-  }
-  inline void fini_shallow (void)
-  {
-    free (items);
-  }
-  inline void fini (void)
-  {
-    hb_object_fini (this);
-    fini_shallow ();
-  }
-
-  inline bool resize (void)
-  {
-    if (unlikely (!successful)) return false;
-
-    unsigned int power = _hb_bit_storage (population * 2 + 8);
-    unsigned int new_size = 1u << power;
-    item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
-    if (unlikely (!new_items))
-    {
-      successful = false;
-      return false;
-    }
-    memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t));
-
-    unsigned int old_size = mask + 1;
-    item_t *old_items = items;
-
-    /* Switch to new, empty, array. */
-    population = occupancy = 0;
-    mask = new_size - 1;
-    prime = prime_for (power);
-    items = new_items;
-
-    /* Insert back old items. */
-    if (old_items)
-      for (unsigned int i = 0; i < old_size; i++)
-        if (old_items[i].key != INVALID && old_items[i].value != INVALID)
-          set (old_items[i].key, old_items[i].value);
-
-    free (old_items);
-
-    return true;
-  }
-
-  inline void set (hb_codepoint_t key, hb_codepoint_t value)
-  {
-    if (unlikely (!successful)) return;
-    if (unlikely (key == INVALID)) return;
-    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
-    unsigned int i = bucket_for (key);
-
-    if (value == INVALID && items[i].key != key)
-      return; /* Trying to delete non-existent key. */
-
-    if (!items[i].is_unused ())
-    {
-      occupancy--;
-      if (items[i].is_tombstone ())
-        population--;
-    }
-
-    items[i].key = key;
-    items[i].value = value;
-
-    occupancy++;
-    if (!items[i].is_tombstone ())
-      population++;
-
-  }
-  inline hb_codepoint_t get (hb_codepoint_t key) const
-  {
-    if (unlikely (!items)) return INVALID;
-    unsigned int i = bucket_for (key);
-    return items[i].key == key ? items[i].value : INVALID;
-  }
-
-  inline void del (hb_codepoint_t key)
-  {
-    set (key, INVALID);
-  }
-  inline bool has (hb_codepoint_t key) const
-  {
-    return get (key) != INVALID;
-  }
-
-  inline hb_codepoint_t operator [] (unsigned int key) const
-  { return get (key); }
-
-  static const hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
-
-  inline void clear (void)
-  {
-    memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
-    population = occupancy = 0;
-  }
-
-  inline bool is_empty (void) const
-  {
-    return population != 0;
-  }
-
-  inline unsigned int get_population () const
-  {
-    return population;
-  }
-
-  protected:
-
-  inline unsigned int bucket_for (hb_codepoint_t key) const
-  {
-    unsigned int i = Hash (key) % prime;
-    unsigned int step = 0;
-    unsigned int tombstone = INVALID;
-    while (!items[i].is_unused ())
-    {
-      if (items[i].key == key)
-        return i;
-      if (tombstone == INVALID && items[i].is_tombstone ())
-        tombstone = i;
-      i = (i + ++step) & mask;
-    }
-    return tombstone == INVALID ? i : tombstone;
-  }
-
-  static inline unsigned int prime_for (unsigned int shift)
-  {
-    /* Following comment and table copied from glib. */
-    /* Each table size has an associated prime modulo (the first prime
-     * lower than the table size) used to find the initial bucket. Probing
-     * then works modulo 2^n. The prime modulo is necessary to get a
-     * good distribution with poor hash functions.
-     */
-    /* Not declaring static to make all kinds of compilers happy... */
-    /*static*/ const unsigned int prime_mod [32] =
-    {
-      1,          /* For 1 << 0 */
-      2,
-      3,
-      7,
-      13,
-      31,
-      61,
-      127,
-      251,
-      509,
-      1021,
-      2039,
-      4093,
-      8191,
-      16381,
-      32749,
-      65521,      /* For 1 << 16 */
-      131071,
-      262139,
-      524287,
-      1048573,
-      2097143,
-      4194301,
-      8388593,
-      16777213,
-      33554393,
-      67108859,
-      134217689,
-      268435399,
-      536870909,
-      1073741789,
-      2147483647  /* For 1 << 31 */
-    };
-
-    if (unlikely (shift >= ARRAY_LENGTH (prime_mod)))
-      return prime_mod[ARRAY_LENGTH (prime_mod) - 1];
-
-    return prime_mod[shift];
-  }
-};
-
-
-#endif /* HB_MAP_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,10 +24,19 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-map-private.hh"
+#include "hb-map.hh"
 
 
-/* Public API */
+/**
+ * SECTION:hb-map
+ * @title: hb-map
+ * @short_description: Object representing integer to integer mapping
+ * @include: hb.h
+ *
+ * Map objects are integer-to-integer hash-maps.  Currently they are
+ * not used in the HarfBuzz public API, but are provided for client's
+ * use if desired.
+ **/
 
 
 /**
@@ -38,7 +47,7 @@
  * Since: 1.7.7
  **/
 hb_map_t *
-hb_map_create (void)
+hb_map_create ()
 {
   hb_map_t *map;
 
@@ -58,7 +67,7 @@
  * Since: 1.7.7
  **/
 hb_map_t *
-hb_map_get_empty (void)
+hb_map_get_empty ()
 {
   return const_cast<hb_map_t *> (&Null(hb_map_t));
 }
@@ -157,8 +166,6 @@
  *
  *
  *
- * Return value:
- *
  * Since: 1.7.7
  **/
 void
@@ -188,7 +195,7 @@
 /**
  * hb_map_del:
  * @map: a map.
- * @codepoint:
+ * @key:
  *
  *
  *
@@ -204,7 +211,7 @@
 /**
  * hb_map_has:
  * @map: a map.
- * @codepoint:
+ * @key:
  *
  *
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-map.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,252 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MAP_HH
+#define HB_MAP_HH
+
+#include "hb.hh"
+
+
+template <typename T>
+inline uint32_t Hash (const T &v)
+{
+  /* Knuth's multiplicative method: */
+  return (uint32_t) v * 2654435761u;
+}
+
+
+/*
+ * hb_map_t
+ */
+
+struct hb_map_t
+{
+  HB_NO_COPY_ASSIGN (hb_map_t);
+  hb_map_t ()  { init (); }
+  ~hb_map_t () { fini (); }
+
+  struct item_t
+  {
+    hb_codepoint_t key;
+    hb_codepoint_t value;
+
+    bool is_unused () const    { return key == INVALID; }
+    bool is_tombstone () const { return key != INVALID && value == INVALID; }
+  };
+
+  hb_object_header_t header;
+  bool successful; /* Allocations successful */
+  unsigned int population; /* Not including tombstones. */
+  unsigned int occupancy; /* Including tombstones. */
+  unsigned int mask;
+  unsigned int prime;
+  item_t *items;
+
+  void init_shallow ()
+  {
+    successful = true;
+    population = occupancy = 0;
+    mask = 0;
+    prime = 0;
+    items = nullptr;
+  }
+  void init ()
+  {
+    hb_object_init (this);
+    init_shallow ();
+  }
+  void fini_shallow ()
+  {
+    free (items);
+    items = nullptr;
+  }
+  void fini ()
+  {
+    population = occupancy = 0;
+    hb_object_fini (this);
+    fini_shallow ();
+  }
+
+  bool in_error () const { return !successful; }
+
+  bool resize ()
+  {
+    if (unlikely (!successful)) return false;
+
+    unsigned int power = hb_bit_storage (population * 2 + 8);
+    unsigned int new_size = 1u << power;
+    item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
+    if (unlikely (!new_items))
+    {
+      successful = false;
+      return false;
+    }
+    memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t));
+
+    unsigned int old_size = mask + 1;
+    item_t *old_items = items;
+
+    /* Switch to new, empty, array. */
+    population = occupancy = 0;
+    mask = new_size - 1;
+    prime = prime_for (power);
+    items = new_items;
+
+    /* Insert back old items. */
+    if (old_items)
+      for (unsigned int i = 0; i < old_size; i++)
+        if (old_items[i].key != INVALID && old_items[i].value != INVALID)
+          set (old_items[i].key, old_items[i].value);
+
+    free (old_items);
+
+    return true;
+  }
+
+  void set (hb_codepoint_t key, hb_codepoint_t value)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (key == INVALID)) return;
+    if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
+    unsigned int i = bucket_for (key);
+
+    if (value == INVALID && items[i].key != key)
+      return; /* Trying to delete non-existent key. */
+
+    if (!items[i].is_unused ())
+    {
+      occupancy--;
+      if (items[i].is_tombstone ())
+        population--;
+    }
+
+    items[i].key = key;
+    items[i].value = value;
+
+    occupancy++;
+    if (!items[i].is_tombstone ())
+      population++;
+
+  }
+  hb_codepoint_t get (hb_codepoint_t key) const
+  {
+    if (unlikely (!items)) return INVALID;
+    unsigned int i = bucket_for (key);
+    return items[i].key == key ? items[i].value : INVALID;
+  }
+
+  void del (hb_codepoint_t key) { set (key, INVALID); }
+
+  bool has (hb_codepoint_t key) const
+  { return get (key) != INVALID; }
+
+  hb_codepoint_t operator [] (unsigned int key) const
+  { return get (key); }
+
+  static constexpr hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
+
+  void clear ()
+  {
+    memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
+    population = occupancy = 0;
+  }
+
+  bool is_empty () const { return population == 0; }
+
+  unsigned int get_population () const { return population; }
+
+  protected:
+
+  unsigned int bucket_for (hb_codepoint_t key) const
+  {
+    unsigned int i = Hash (key) % prime;
+    unsigned int step = 0;
+    unsigned int tombstone = INVALID;
+    while (!items[i].is_unused ())
+    {
+      if (items[i].key == key)
+        return i;
+      if (tombstone == INVALID && items[i].is_tombstone ())
+        tombstone = i;
+      i = (i + ++step) & mask;
+    }
+    return tombstone == INVALID ? i : tombstone;
+  }
+
+  static unsigned int prime_for (unsigned int shift)
+  {
+    /* Following comment and table copied from glib. */
+    /* Each table size has an associated prime modulo (the first prime
+     * lower than the table size) used to find the initial bucket. Probing
+     * then works modulo 2^n. The prime modulo is necessary to get a
+     * good distribution with poor hash functions.
+     */
+    /* Not declaring static to make all kinds of compilers happy... */
+    /*static*/ const unsigned int prime_mod [32] =
+    {
+      1,          /* For 1 << 0 */
+      2,
+      3,
+      7,
+      13,
+      31,
+      61,
+      127,
+      251,
+      509,
+      1021,
+      2039,
+      4093,
+      8191,
+      16381,
+      32749,
+      65521,      /* For 1 << 16 */
+      131071,
+      262139,
+      524287,
+      1048573,
+      2097143,
+      4194301,
+      8388593,
+      16777213,
+      33554393,
+      67108859,
+      134217689,
+      268435399,
+      536870909,
+      1073741789,
+      2147483647  /* For 1 << 31 */
+    };
+
+    if (unlikely (shift >= ARRAY_LENGTH (prime_mod)))
+      return prime_mod[ARRAY_LENGTH (prime_mod) - 1];
+
+    return prime_mod[shift];
+  }
+};
+
+
+#endif /* HB_MAP_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Contributor(s):
- *      Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_MUTEX_PRIVATE_HH
-#define HB_MUTEX_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* mutex */
-
-/* We need external help for these */
-
-#if defined(HB_MUTEX_IMPL_INIT) \
- && defined(hb_mutex_impl_init) \
- && defined(hb_mutex_impl_lock) \
- && defined(hb_mutex_impl_unlock) \
- && defined(hb_mutex_impl_finish)
-
-/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
-
-
-#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__))
-
-#include <windows.h>
-typedef CRITICAL_SECTION hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      {0}
-#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#define hb_mutex_impl_init(M)   InitializeCriticalSectionEx (M, 0, 0)
-#else
-#define hb_mutex_impl_init(M)   InitializeCriticalSection (M)
-#endif
-#define hb_mutex_impl_lock(M)   EnterCriticalSection (M)
-#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
-#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
-
-
-#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
-
-#include <pthread.h>
-typedef pthread_mutex_t hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      PTHREAD_MUTEX_INITIALIZER
-#define hb_mutex_impl_init(M)   pthread_mutex_init (M, nullptr)
-#define hb_mutex_impl_lock(M)   pthread_mutex_lock (M)
-#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M)
-#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M)
-
-
-#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-/* This actually is not a totally awful implementation. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      0
-#define hb_mutex_impl_init(M)   *(M) = 0
-#define hb_mutex_impl_lock(M)   HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
-#define hb_mutex_impl_unlock(M) __sync_lock_release (M)
-#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
-
-
-#elif !defined(HB_NO_MT)
-
-#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
-# include <sched.h>
-# define HB_SCHED_YIELD() sched_yield ()
-#else
-# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
-#endif
-
-#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
-typedef volatile int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      0
-#define hb_mutex_impl_init(M)   *(M) = 0
-#define hb_mutex_impl_lock(M)   HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
-#define hb_mutex_impl_unlock(M) (*(M))--;
-#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
-
-
-#else /* HB_NO_MT */
-
-typedef int hb_mutex_impl_t;
-#define HB_MUTEX_IMPL_INIT      0
-#define hb_mutex_impl_init(M)   HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_lock(M)   HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END
-#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
-
-
-#endif
-
-
-#define HB_MUTEX_INIT           {HB_MUTEX_IMPL_INIT}
-
-struct hb_mutex_t
-{
-  /* TODO Add tracing. */
-
-  hb_mutex_impl_t m;
-
-  inline void init   (void) { hb_mutex_impl_init   (&m); }
-  inline void lock   (void) { hb_mutex_impl_lock   (&m); }
-  inline void unlock (void) { hb_mutex_impl_unlock (&m); }
-  inline void fini (void) { hb_mutex_impl_finish (&m); }
-};
-
-
-#endif /* HB_MUTEX_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-mutex.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2007  Chris Wilson
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Contributor(s):
+ *      Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_MUTEX_HH
+#define HB_MUTEX_HH
+
+#include "hb.hh"
+
+
+/* mutex */
+
+/* We need external help for these */
+
+#if defined(HB_MUTEX_IMPL_INIT) \
+ && defined(hb_mutex_impl_init) \
+ && defined(hb_mutex_impl_lock) \
+ && defined(hb_mutex_impl_unlock) \
+ && defined(hb_mutex_impl_finish)
+
+/* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
+
+
+#elif !defined(HB_NO_MT) && defined(_WIN32)
+
+#include <windows.h>
+typedef CRITICAL_SECTION hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      {0}
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#define hb_mutex_impl_init(M)   InitializeCriticalSectionEx (M, 0, 0)
+#else
+#define hb_mutex_impl_init(M)   InitializeCriticalSection (M)
+#endif
+#define hb_mutex_impl_lock(M)   EnterCriticalSection (M)
+#define hb_mutex_impl_unlock(M) LeaveCriticalSection (M)
+#define hb_mutex_impl_finish(M) DeleteCriticalSection (M)
+
+
+#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
+
+#include <pthread.h>
+typedef pthread_mutex_t hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      PTHREAD_MUTEX_INITIALIZER
+#define hb_mutex_impl_init(M)   pthread_mutex_init (M, nullptr)
+#define hb_mutex_impl_lock(M)   pthread_mutex_lock (M)
+#define hb_mutex_impl_unlock(M) pthread_mutex_unlock (M)
+#define hb_mutex_impl_finish(M) pthread_mutex_destroy (M)
+
+
+#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define HB_SCHED_YIELD() sched_yield ()
+#else
+# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
+#endif
+
+/* This actually is not a totally awful implementation. */
+typedef volatile int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      0
+#define hb_mutex_impl_init(M)   *(M) = 0
+#define hb_mutex_impl_lock(M)   HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END
+#define hb_mutex_impl_unlock(M) __sync_lock_release (M)
+#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
+
+
+#elif !defined(HB_NO_MT)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define HB_SCHED_YIELD() sched_yield ()
+#else
+# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
+#endif
+
+#define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
+typedef volatile int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      0
+#define hb_mutex_impl_init(M)   *(M) = 0
+#define hb_mutex_impl_lock(M)   HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
+#define hb_mutex_impl_unlock(M) (*(M))--;
+#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
+
+
+#else /* HB_NO_MT */
+
+typedef int hb_mutex_impl_t;
+#define HB_MUTEX_IMPL_INIT      0
+#define hb_mutex_impl_init(M)   HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_lock(M)   HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_unlock(M) HB_STMT_START {} HB_STMT_END
+#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END
+
+
+#endif
+
+
+#define HB_MUTEX_INIT           {HB_MUTEX_IMPL_INIT}
+
+struct hb_mutex_t
+{
+  /* TODO Add tracing. */
+
+  hb_mutex_impl_t m;
+
+  void init   () { hb_mutex_impl_init   (&m); }
+  void lock   () { hb_mutex_impl_lock   (&m); }
+  void unlock () { hb_mutex_impl_unlock (&m); }
+  void fini ()   { hb_mutex_impl_finish (&m); }
+};
+
+struct hb_lock_t
+{
+  hb_lock_t (hb_mutex_t &mutex_) : mutex (mutex_) { mutex.lock (); }
+  ~hb_lock_t () { mutex.unlock (); }
+  private:
+  hb_mutex_t &mutex;
+};
+
+
+#endif /* HB_MUTEX_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-null.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,204 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_NULL_HH
+#define HB_NULL_HH
+
+#include "hb.hh"
+
+
+/*
+ * Static pools
+ */
+
+/* Global nul-content Null pool.  Enlarge as necessary. */
+
+#define HB_NULL_POOL_SIZE 9880
+
+/* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
+ * otherwise return sizeof(T). */
+
+/* The hard way...
+ * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
+ */
+
+template<bool> struct _hb_bool_type {};
+
+template <typename T, typename B>
+struct _hb_null_size
+{ enum { value = sizeof (T) }; };
+template <typename T>
+struct _hb_null_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ enum { value = T::null_size }; };
+
+template <typename T>
+struct hb_null_size
+{ enum { value = _hb_null_size<T, _hb_bool_type<true> >::value }; };
+#define hb_null_size(T) hb_null_size<T>::value
+
+/* These doesn't belong here, but since is copy/paste from above, put it here. */
+
+/* hb_static_size (T)
+ * Returns T::static_size if T::min_size is defined, or sizeof (T) otherwise. */
+
+template <typename T, typename B>
+struct _hb_static_size
+{ enum { value = sizeof (T) }; };
+template <typename T>
+struct _hb_static_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ enum { value = T::static_size }; };
+
+template <typename T>
+struct hb_static_size
+{ enum { value = _hb_static_size<T, _hb_bool_type<true> >::value }; };
+#define hb_static_size(T) hb_static_size<T>::value
+
+
+/* hb_assign (obj, value)
+ * Calls obj.set (value) if obj.min_size is defined and value has different type
+ * from obj, or obj = v otherwise. */
+
+template <typename T, typename V, typename B>
+struct _hb_assign
+{ static inline void value (T &o, const V v) { o = v; } };
+template <typename T, typename V>
+struct _hb_assign<T, V, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ static inline void value (T &o, const V v) { o.set (v); } };
+template <typename T>
+struct _hb_assign<T, T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
+{ static inline void value (T &o, const T v) { o = v; } };
+
+template <typename T, typename V>
+static inline void hb_assign (T &o, const V v)
+{ _hb_assign<T, V, _hb_bool_type<true> >::value (o, v); }
+
+
+/*
+ * Null()
+ */
+
+extern HB_INTERNAL
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* Generic nul-content Null objects. */
+template <typename Type>
+static inline Type const & Null () {
+  static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+  return *reinterpret_cast<Type const *> (_hb_NullPool);
+}
+template <typename QType>
+struct NullHelper
+{
+  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
+  static const Type & get_null () { return Null<Type> (); }
+};
+#define Null(Type) NullHelper<Type>::get_null ()
+
+/* Specializations for arbitrary-content Null objects expressed in bytes. */
+#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+        } /* Close namespace. */ \
+        extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
+        template <> \
+        /*static*/ inline const Namespace::Type& Null<Namespace::Type> () { \
+          return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
+        } \
+        namespace Namespace { \
+        static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+        const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
+
+/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
+#define DECLARE_NULL_INSTANCE(Type) \
+        extern HB_INTERNAL const Type _hb_Null_##Type; \
+        template <> \
+        /*static*/ inline const Type& Null<Type> () { \
+          return _hb_Null_##Type; \
+        } \
+static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_INSTANCE(Type) \
+        const Type _hb_Null_##Type
+
+/* Global writable pool.  Enlarge as necessary. */
+
+/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
+ * for correct operation. It only exist to catch and divert program logic bugs instead of
+ * causing bad memory access. So, races there are not actually introducing incorrectness
+ * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
+extern HB_INTERNAL
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* CRAP pool: Common Region for Access Protection. */
+template <typename Type>
+static inline Type& Crap () {
+  static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+  Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
+  memcpy (obj, &Null(Type), sizeof (*obj));
+  return *obj;
+}
+template <typename QType>
+struct CrapHelper
+{
+  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
+  static Type & get_crap () { return Crap<Type> (); }
+};
+#define Crap(Type) CrapHelper<Type>::get_crap ()
+
+template <typename Type>
+struct CrapOrNullHelper {
+  static Type & get () { return Crap(Type); }
+};
+template <typename Type>
+struct CrapOrNullHelper<const Type> {
+  static const Type & get () { return Null(Type); }
+};
+#define CrapOrNull(Type) CrapOrNullHelper<Type>::get ()
+
+
+/*
+ * hb_nonnull_ptr_t
+ */
+
+template <typename P>
+struct hb_nonnull_ptr_t
+{
+  typedef typename hb_remove_pointer (P) T;
+
+  hb_nonnull_ptr_t (T *v_ = nullptr) : v (v_) {}
+  T * operator = (T *v_)   { return v = v_; }
+  T * operator -> () const { return get (); }
+  T & operator * () const  { return *get (); }
+  T ** operator & () const { return &v; }
+  /* Only auto-cast to const types. */
+  template <typename C> operator const C * () const { return get (); }
+  operator const char * () const { return (const char *) get (); }
+  T * get () const { return v ? v : const_cast<T *> (&Null(T)); }
+  T * get_raw () const { return v; }
+
+  T *v;
+};
+
+
+#endif /* HB_NULL_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,221 +0,0 @@
-/*
- * Copyright © 2007  Chris Wilson
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Contributor(s):
- *      Chris Wilson <chris@chris-wilson.co.uk>
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OBJECT_PRIVATE_HH
-#define HB_OBJECT_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-
-#include "hb-atomic-private.hh"
-#include "hb-mutex-private.hh"
-
-
-/* reference_count */
-
-#define HB_REFERENCE_COUNT_INERT_VALUE 0
-#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
-#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
-
-struct hb_reference_count_t
-{
-  hb_atomic_int_t ref_count;
-
-  inline void init (int v) { ref_count.set_unsafe (v); }
-  inline int get_unsafe (void) const { return ref_count.get_unsafe (); }
-  inline int inc (void) { return ref_count.inc (); }
-  inline int dec (void) { return ref_count.dec (); }
-  inline void fini (void) { ref_count.set_unsafe (HB_REFERENCE_COUNT_POISON_VALUE); }
-
-  inline bool is_inert (void) const { return ref_count.get_unsafe () == HB_REFERENCE_COUNT_INERT_VALUE; }
-  inline bool is_valid (void) const { return ref_count.get_unsafe () > 0; }
-};
-
-
-/* user_data */
-
-struct hb_user_data_array_t
-{
-  struct hb_user_data_item_t {
-    hb_user_data_key_t *key;
-    void *data;
-    hb_destroy_func_t destroy;
-
-    inline bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
-    inline bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
-
-    void fini (void) { if (destroy) destroy (data); }
-  };
-
-  hb_mutex_t lock;
-  hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items;
-
-  inline void init (void) { lock.init (); items.init (); }
-
-  HB_INTERNAL bool set (hb_user_data_key_t *key,
-                        void *              data,
-                        hb_destroy_func_t   destroy,
-                        hb_bool_t           replace);
-
-  HB_INTERNAL void *get (hb_user_data_key_t *key);
-
-  inline void fini (void) { items.fini (lock); lock.fini (); }
-};
-
-
-/* object_header */
-
-struct hb_object_header_t
-{
-  hb_reference_count_t ref_count;
-  hb_user_data_array_t *user_data;
-
-#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, nullptr}
-
-  private:
-  ASSERT_POD ();
-};
-
-
-/* object */
-
-template <typename Type>
-static inline void hb_object_trace (const Type *obj, const char *function)
-{
-  DEBUG_MSG (OBJECT, (void *) obj,
-             "%s refcount=%d",
-             function,
-             obj ? obj->header.ref_count.get_unsafe () : 0);
-}
-
-template <typename Type>
-static inline Type *hb_object_create (void)
-{
-  Type *obj = (Type *) calloc (1, sizeof (Type));
-
-  if (unlikely (!obj))
-    return obj;
-
-  hb_object_init (obj);
-  hb_object_trace (obj, HB_FUNC);
-  return obj;
-}
-template <typename Type>
-static inline void hb_object_init (Type *obj)
-{
-  obj->header.ref_count.init (1);
-  obj->header.user_data = nullptr;
-}
-template <typename Type>
-static inline bool hb_object_is_inert (const Type *obj)
-{
-  return unlikely (obj->header.ref_count.is_inert ());
-}
-template <typename Type>
-static inline bool hb_object_is_valid (const Type *obj)
-{
-  return likely (obj->header.ref_count.is_valid ());
-}
-template <typename Type>
-static inline Type *hb_object_reference (Type *obj)
-{
-  hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return obj;
-  assert (hb_object_is_valid (obj));
-  obj->header.ref_count.inc ();
-  return obj;
-}
-template <typename Type>
-static inline bool hb_object_destroy (Type *obj)
-{
-  hb_object_trace (obj, HB_FUNC);
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return false;
-  assert (hb_object_is_valid (obj));
-  if (obj->header.ref_count.dec () != 1)
-    return false;
-
-  hb_object_fini (obj);
-  return true;
-}
-template <typename Type>
-static inline void hb_object_fini (Type *obj)
-{
-  obj->header.ref_count.fini (); /* Do this before user_data */
-  if (obj->header.user_data)
-  {
-    obj->header.user_data->fini ();
-    free (obj->header.user_data);
-  }
-}
-template <typename Type>
-static inline bool hb_object_set_user_data (Type               *obj,
-                                            hb_user_data_key_t *key,
-                                            void *              data,
-                                            hb_destroy_func_t   destroy,
-                                            hb_bool_t           replace)
-{
-  if (unlikely (!obj || hb_object_is_inert (obj)))
-    return false;
-  assert (hb_object_is_valid (obj));
-
-retry:
-  hb_user_data_array_t *user_data = (hb_user_data_array_t *) hb_atomic_ptr_get (&obj->header.user_data);
-  if (unlikely (!user_data))
-  {
-    user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
-    if (unlikely (!user_data))
-      return false;
-    user_data->init ();
-    if (unlikely (!hb_atomic_ptr_cmpexch (&obj->header.user_data, nullptr, user_data)))
-    {
-      user_data->fini ();
-      free (user_data);
-      goto retry;
-    }
-  }
-
-  return user_data->set (key, data, destroy, replace);
-}
-
-template <typename Type>
-static inline void *hb_object_get_user_data (Type               *obj,
-                                             hb_user_data_key_t *key)
-{
-  if (unlikely (!obj || hb_object_is_inert (obj) || !obj->header.user_data))
-    return nullptr;
-  assert (hb_object_is_valid (obj));
-  return obj->header.user_data->get (key);
-}
-
-
-#endif /* HB_OBJECT_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-object.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,342 @@
+/*
+ * Copyright © 2007  Chris Wilson
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Contributor(s):
+ *      Chris Wilson <chris@chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OBJECT_HH
+#define HB_OBJECT_HH
+
+#include "hb.hh"
+#include "hb-atomic.hh"
+#include "hb-mutex.hh"
+#include "hb-vector.hh"
+
+
+/*
+ * Lockable set
+ */
+
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
+{
+  hb_vector_t<item_t> items;
+
+  void init () { items.init (); }
+
+  template <typename T>
+  item_t *replace_or_insert (T v, lock_t &l, bool replace)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item) {
+      if (replace) {
+        item_t old = *item;
+        *item = v;
+        l.unlock ();
+        old.fini ();
+      }
+      else {
+        item = nullptr;
+        l.unlock ();
+      }
+    } else {
+      item = items.push (v);
+      l.unlock ();
+    }
+    return item;
+  }
+
+  template <typename T>
+  void remove (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item)
+    {
+      item_t old = *item;
+      *item = items[items.length - 1];
+      items.pop ();
+      l.unlock ();
+      old.fini ();
+    } else {
+      l.unlock ();
+    }
+  }
+
+  template <typename T>
+  bool find (T v, item_t *i, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item)
+      *i = *item;
+    l.unlock ();
+    return !!item;
+  }
+
+  template <typename T>
+  item_t *find_or_insert (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (!item) {
+      item = items.push (v);
+    }
+    l.unlock ();
+    return item;
+  }
+
+  void fini (lock_t &l)
+  {
+    if (!items.length)
+    {
+      /* No need to lock. */
+      items.fini ();
+      return;
+    }
+    l.lock ();
+    while (items.length)
+    {
+      item_t old = items[items.length - 1];
+      items.pop ();
+      l.unlock ();
+      old.fini ();
+      l.lock ();
+    }
+    items.fini ();
+    l.unlock ();
+  }
+
+};
+
+
+/*
+ * Reference-count.
+ */
+
+#define HB_REFERENCE_COUNT_INERT_VALUE 0
+#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
+#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)}
+
+struct hb_reference_count_t
+{
+  mutable hb_atomic_int_t ref_count;
+
+  void init (int v = 1) { ref_count.set_relaxed (v); }
+  int get_relaxed () const { return ref_count.get_relaxed (); }
+  int inc () const { return ref_count.inc (); }
+  int dec () const { return ref_count.dec (); }
+  void fini () { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); }
+
+  bool is_inert () const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; }
+  bool is_valid () const { return ref_count.get_relaxed () > 0; }
+};
+
+
+/* user_data */
+
+struct hb_user_data_array_t
+{
+  struct hb_user_data_item_t {
+    hb_user_data_key_t *key;
+    void *data;
+    hb_destroy_func_t destroy;
+
+    bool operator == (hb_user_data_key_t *other_key) const { return key == other_key; }
+    bool operator == (hb_user_data_item_t &other) const { return key == other.key; }
+
+    void fini () { if (destroy) destroy (data); }
+  };
+
+  hb_mutex_t lock;
+  hb_lockable_set_t<hb_user_data_item_t, hb_mutex_t> items;
+
+  void init () { lock.init (); items.init (); }
+
+  HB_INTERNAL bool set (hb_user_data_key_t *key,
+                        void *              data,
+                        hb_destroy_func_t   destroy,
+                        hb_bool_t           replace);
+
+  HB_INTERNAL void *get (hb_user_data_key_t *key);
+
+  void fini () { items.fini (lock); lock.fini (); }
+};
+
+
+/*
+ * Object header
+ */
+
+struct hb_object_header_t
+{
+  hb_reference_count_t ref_count;
+  mutable hb_atomic_int_t writable;
+  hb_atomic_ptr_t<hb_user_data_array_t> user_data;
+};
+#define HB_OBJECT_HEADER_STATIC \
+        { \
+          HB_REFERENCE_COUNT_INIT, \
+          HB_ATOMIC_INT_INIT (false), \
+          HB_ATOMIC_PTR_INIT (nullptr) \
+        }
+
+
+/*
+ * Object
+ */
+
+template <typename Type>
+static inline void hb_object_trace (const Type *obj, const char *function)
+{
+  DEBUG_MSG (OBJECT, (void *) obj,
+             "%s refcount=%d",
+             function,
+             obj ? obj->header.ref_count.get_relaxed () : 0);
+}
+
+template <typename Type>
+static inline Type *hb_object_create ()
+{
+  Type *obj = (Type *) calloc (1, sizeof (Type));
+
+  if (unlikely (!obj))
+    return obj;
+
+  hb_object_init (obj);
+  hb_object_trace (obj, HB_FUNC);
+  return obj;
+}
+template <typename Type>
+static inline void hb_object_init (Type *obj)
+{
+  obj->header.ref_count.init ();
+  obj->header.writable.set_relaxed (true);
+  obj->header.user_data.init ();
+}
+template <typename Type>
+static inline bool hb_object_is_inert (const Type *obj)
+{
+  return unlikely (obj->header.ref_count.is_inert ());
+}
+template <typename Type>
+static inline bool hb_object_is_valid (const Type *obj)
+{
+  return likely (obj->header.ref_count.is_valid ());
+}
+template <typename Type>
+static inline bool hb_object_is_immutable (const Type *obj)
+{
+  return !obj->header.writable.get_relaxed ();
+}
+template <typename Type>
+static inline void hb_object_make_immutable (const Type *obj)
+{
+  obj->header.writable.set_relaxed (false);
+}
+template <typename Type>
+static inline Type *hb_object_reference (Type *obj)
+{
+  hb_object_trace (obj, HB_FUNC);
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return obj;
+  assert (hb_object_is_valid (obj));
+  obj->header.ref_count.inc ();
+  return obj;
+}
+template <typename Type>
+static inline bool hb_object_destroy (Type *obj)
+{
+  hb_object_trace (obj, HB_FUNC);
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return false;
+  assert (hb_object_is_valid (obj));
+  if (obj->header.ref_count.dec () != 1)
+    return false;
+
+  hb_object_fini (obj);
+  return true;
+}
+template <typename Type>
+static inline void hb_object_fini (Type *obj)
+{
+  obj->header.ref_count.fini (); /* Do this before user_data */
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (user_data)
+  {
+    user_data->fini ();
+    free (user_data);
+    user_data = nullptr;
+  }
+}
+template <typename Type>
+static inline bool hb_object_set_user_data (Type               *obj,
+                                            hb_user_data_key_t *key,
+                                            void *              data,
+                                            hb_destroy_func_t   destroy,
+                                            hb_bool_t           replace)
+{
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return false;
+  assert (hb_object_is_valid (obj));
+
+retry:
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (unlikely (!user_data))
+  {
+    user_data = (hb_user_data_array_t *) calloc (sizeof (hb_user_data_array_t), 1);
+    if (unlikely (!user_data))
+      return false;
+    user_data->init ();
+    if (unlikely (!obj->header.user_data.cmpexch (nullptr, user_data)))
+    {
+      user_data->fini ();
+      free (user_data);
+      goto retry;
+    }
+  }
+
+  return user_data->set (key, data, destroy, replace);
+}
+
+template <typename Type>
+static inline void *hb_object_get_user_data (Type               *obj,
+                                             hb_user_data_key_t *key)
+{
+  if (unlikely (!obj || hb_object_is_inert (obj)))
+    return nullptr;
+  assert (hb_object_is_valid (obj));
+  hb_user_data_array_t *user_data = obj->header.user_data.get ();
+  if (!user_data)
+    return nullptr;
+  return user_data->get (key);
+}
+
+
+#endif /* HB_OBJECT_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,570 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OPEN_FILE_PRIVATE_HH
-#define HB_OPEN_FILE_PRIVATE_HH
-
-#include "hb-open-type-private.hh"
-#include "hb-ot-head-table.hh"
-
-
-namespace OT {
-
-
-/*
- *
- * The OpenType Font File
- *
- */
-
-
-/*
- * Organization of an OpenType Font
- */
-
-struct OpenTypeFontFile;
-struct OffsetTable;
-struct TTCHeader;
-
-
-typedef struct TableRecord
-{
-  int cmp (Tag t) const
-  { return -t.cmp (tag); }
-
-  static int cmp (const void *pa, const void *pb)
-  {
-    const TableRecord *a = (const TableRecord *) pa;
-    const TableRecord *b = (const TableRecord *) pb;
-    return b->cmp (a->tag);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  Tag           tag;            /* 4-byte identifier. */
-  CheckSum      checkSum;       /* CheckSum for this table. */
-  Offset32      offset;         /* Offset from beginning of TrueType font
-                                 * file. */
-  HBUINT32      length;         /* Length of this table. */
-  public:
-  DEFINE_SIZE_STATIC (16);
-} OpenTypeTable;
-
-typedef struct OffsetTable
-{
-  friend struct OpenTypeFontFile;
-
-  inline unsigned int get_table_count (void) const
-  { return tables.len; }
-  inline const TableRecord& get_table (unsigned int i) const
-  {
-    return tables[i];
-  }
-  inline unsigned int get_table_tags (unsigned int  start_offset,
-                                      unsigned int *table_count, /* IN/OUT */
-                                      hb_tag_t     *table_tags /* OUT */) const
-  {
-    if (table_count)
-    {
-      if (start_offset >= tables.len)
-        *table_count = 0;
-      else
-        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
-
-      const TableRecord *sub_tables = tables.arrayZ + start_offset;
-      unsigned int count = *table_count;
-      for (unsigned int i = 0; i < count; i++)
-        table_tags[i] = sub_tables[i].tag;
-    }
-    return tables.len;
-  }
-  inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
-  {
-    Tag t;
-    t.set (tag);
-    /* Linear-search for small tables to work around fonts with unsorted
-     * table list. */
-    int i = tables.len < 64 ? tables.lsearch (t) : tables.bsearch (t);
-    if (table_index)
-      *table_index = i == -1 ? Index::NOT_FOUND_INDEX : (unsigned int) i;
-    return i != -1;
-  }
-  inline const TableRecord& get_table_by_tag (hb_tag_t tag) const
-  {
-    unsigned int table_index;
-    find_table_index (tag, &table_index);
-    return get_table (table_index);
-  }
-
-  public:
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         hb_tag_t sfnt_tag,
-                         Supplier<hb_tag_t> &tags,
-                         Supplier<hb_blob_t *> &blobs,
-                         unsigned int table_count)
-  {
-    TRACE_SERIALIZE (this);
-    /* Alloc 12 for the OTHeader. */
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    /* Write sfntVersion (bytes 0..3). */
-    sfnt_version.set (sfnt_tag);
-    /* Take space for numTables, searchRange, entrySelector, RangeShift
-     * and the TableRecords themselves.  */
-    if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
-
-    const char *dir_end = (const char *) c->head;
-    HBUINT32 *checksum_adjustment = nullptr;
-
-    /* Write OffsetTables, alloc for and write actual table blobs. */
-    for (unsigned int i = 0; i < table_count; i++)
-    {
-      TableRecord &rec = tables.arrayZ[i];
-      hb_blob_t *blob = blobs[i];
-      rec.tag.set (tags[i]);
-      rec.length.set (hb_blob_get_length (blob));
-      rec.offset.serialize (c, this);
-
-      /* Allocate room for the table and copy it. */
-      char *start = (char *) c->allocate_size<void> (rec.length);
-      if (unlikely (!start)) {return false;}
-
-      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
-
-      /* 4-byte allignment. */
-      if (rec.length % 4)
-        c->allocate_size<void> (4 - rec.length % 4);
-      const char *end = (const char *) c->head;
-
-      if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size)
-      {
-        head *h = (head *) start;
-        checksum_adjustment = &h->checkSumAdjustment;
-        checksum_adjustment->set (0);
-      }
-
-      rec.checkSum.set_for_data (start, end - start);
-    }
-    tags += table_count;
-    blobs += table_count;
-
-    tables.qsort ();
-
-    if (checksum_adjustment)
-    {
-      CheckSum checksum;
-
-      /* The following line is a slower version of the following block. */
-      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
-      checksum.set_for_data (this, dir_end - (const char *) this);
-      for (unsigned int i = 0; i < table_count; i++)
-      {
-        TableRecord &rec = tables.arrayZ[i];
-        checksum.set (checksum + rec.checkSum);
-      }
-
-      checksum_adjustment->set (0xB1B0AFBAu - checksum);
-    }
-
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && tables.sanitize (c));
-  }
-
-  protected:
-  Tag           sfnt_version;   /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
-  BinSearchArrayOf<TableRecord>
-                tables;
-  public:
-  DEFINE_SIZE_ARRAY (12, tables);
-} OpenTypeFontFace;
-
-
-/*
- * TrueType Collections
- */
-
-struct TTCHeaderVersion1
-{
-  friend struct TTCHeader;
-
-  inline unsigned int get_face_count (void) const { return table.len; }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (table.sanitize (c, this));
-  }
-
-  protected:
-  Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
-  FixedVersion<>version;        /* Version of the TTC Header (1.0),
-                                 * 0x00010000u */
-  LArrayOf<LOffsetTo<OffsetTable> >
-                table;          /* Array of offsets to the OffsetTable for each font
-                                 * from the beginning of the file */
-  public:
-  DEFINE_SIZE_ARRAY (12, table);
-};
-
-struct TTCHeader
-{
-  friend struct OpenTypeFontFile;
-
-  private:
-
-  inline unsigned int get_face_count (void) const
-  {
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face_count ();
-    default:return 0;
-    }
-  }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return u.version1.get_face (i);
-    default:return Null(OpenTypeFontFace);
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
-    switch (u.header.version.major) {
-    case 2: /* version 2 is compatible with version 1 */
-    case 1: return_trace (u.version1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  struct {
-  Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
-  FixedVersion<>version;        /* Version of the TTC Header (1.0 or 2.0),
-                                 * 0x00010000u or 0x00020000u */
-  }                     header;
-  TTCHeaderVersion1     version1;
-  } u;
-};
-
-/*
- * Mac Resource Fork
- */
-
-struct ResourceRefItem
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    // actual data sanitization is done on ResourceForkHeader sanitizer
-    return_trace (likely (c->check_struct (this)));
-  }
-
-  HBINT16       id;             /* Resource ID, is really should be signed? */
-  HBINT16       nameOffset;     /* Offset from beginning of resource name list
-                                 * to resource name, minus means there is no */
-  HBUINT8       attr;           /* Resource attributes */
-  HBUINT24      dataOffset;     /* Offset from beginning of resource data to
-                                 * data for this resource */
-  HBUINT32      reserved;       /* Reserved for handle to resource */
-  public:
-  DEFINE_SIZE_STATIC (12);
-};
-
-struct ResourceTypeItem
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    // RefList sanitization is done on ResourceMap sanitizer
-    return_trace (likely (c->check_struct (this)));
-  }
-
-  inline unsigned int get_resource_count () const
-  {
-    return numRes + 1;
-  }
-
-  inline bool is_sfnt () const
-  {
-    return type == HB_TAG ('s','f','n','t');
-  }
-
-  inline const ResourceRefItem& get_ref_item (const void *base,
-                                              unsigned int i) const
-  {
-    return (base+refList)[i];
-  }
-
-  protected:
-  Tag           type;           /* Resource type */
-  HBUINT16      numRes;         /* Number of resource this type in map minus 1 */
-  OffsetTo<UnsizedArrayOf<ResourceRefItem> >
-                refList;        /* Offset from beginning of resource type list
-                                 * to reference list for this type */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct ResourceMap
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-    for (unsigned int i = 0; i < get_types_count (); ++i)
-    {
-      const ResourceTypeItem& type = get_type (i);
-      if (unlikely (!type.sanitize (c)))
-        return_trace (false);
-      for (unsigned int j = 0; j < type.get_resource_count (); ++j)
-        if (unlikely (!get_ref_item (type, j).sanitize (c)))
-          return_trace (false);
-    }
-    return_trace (true);
-  }
-
-  inline const ResourceTypeItem& get_type (unsigned int i) const
-  {
-    // Why offset from the second byte of the object? I'm not sure
-    return ((&reserved[2])+typeList)[i];
-  }
-
-  inline unsigned int get_types_count () const
-  {
-    return nTypes + 1;
-  }
-
-  inline const ResourceRefItem &get_ref_item (const ResourceTypeItem &type,
-                                              unsigned int i) const
-  {
-    return type.get_ref_item (&(this+typeList), i);
-  }
-
-  inline const PString& get_name (const ResourceRefItem &item,
-                                  unsigned int i) const
-  {
-    if (item.nameOffset == -1)
-      return Null (PString);
-
-    return StructAtOffset<PString> (this, nameList + item.nameOffset);
-  }
-
-  protected:
-  HBUINT8       reserved[16];   /* Reserved for copy of resource header */
-  LOffsetTo<ResourceMap>
-                reserved1;      /* Reserved for handle to next resource map */
-  HBUINT16      reserved2;      /* Reserved for file reference number */
-  HBUINT16      attr;           /* Resource fork attribute */
-  OffsetTo<UnsizedArrayOf<ResourceTypeItem> >
-                typeList;       /* Offset from beginning of map to
-                                 * resource type list */
-  HBUINT16      nameList;       /* Offset from beginning of map to
-                                 * resource name list */
-  HBUINT16      nTypes;         /* Number of types in the map minus 1 */
-  public:
-  DEFINE_SIZE_STATIC (30);
-};
-
-struct ResourceForkHeader
-{
-  inline unsigned int get_face_count () const
-  {
-    const ResourceMap &resource_map = this+map;
-    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
-    {
-      const ResourceTypeItem& type = resource_map.get_type (i);
-      if (type.is_sfnt ())
-        return type.get_resource_count ();
-    }
-    return 0;
-  }
-
-  inline const LArrayOf<HBUINT8>& get_data (const ResourceTypeItem& type,
-                                            unsigned int idx) const
-  {
-    const ResourceMap &resource_map = this+map;
-    unsigned int offset = dataOffset;
-    offset += resource_map.get_ref_item (type, idx).dataOffset;
-    return StructAtOffset<LArrayOf<HBUINT8> > (this, offset);
-  }
-
-  inline const OpenTypeFontFace& get_face (unsigned int idx) const
-  {
-    const ResourceMap &resource_map = this+map;
-    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
-    {
-      const ResourceTypeItem& type = resource_map.get_type (i);
-      if (type.is_sfnt () && idx < type.get_resource_count ())
-        return (OpenTypeFontFace&) get_data (type, idx).arrayZ;
-    }
-    return Null (OpenTypeFontFace);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-
-    const ResourceMap &resource_map = this+map;
-    if (unlikely (!resource_map.sanitize (c)))
-      return_trace (false);
-
-    for (unsigned int i = 0; i < resource_map.get_types_count (); ++i)
-    {
-      const ResourceTypeItem& type = resource_map.get_type (i);
-      for (unsigned int j = 0; j < type.get_resource_count (); ++j)
-      {
-        const LArrayOf<HBUINT8>& data = get_data (type, j);
-        if (unlikely (!(data.sanitize (c) &&
-                        ((OpenTypeFontFace&) data.arrayZ).sanitize (c))))
-          return_trace (false);
-      }
-    }
-
-    return_trace (true);
-  }
-
-  protected:
-  HBUINT32      dataOffset;     /* Offset from beginning of resource fork
-                                 * to resource data */
-  LOffsetTo<ResourceMap>
-                map;            /* Offset from beginning of resource fork
-                                 * to resource map */
-  HBUINT32      dataLen;        /* Length of resource data */
-  HBUINT32      mapLen;         /* Length of resource map */
-  public:
-  DEFINE_SIZE_STATIC (16);
-};
-
-/*
- * OpenType Font File
- */
-
-struct OpenTypeFontFile
-{
-  static const hb_tag_t tableTag        = HB_TAG ('_','_','_','_'); /* Sanitizer needs this. */
-
-  enum {
-    CFFTag              = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
-    TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
-    TTCTag              = HB_TAG ('t','t','c','f'), /* TrueType Collection */
-    DFontTag            = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
-    TrueTag             = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
-    Typ1Tag             = HB_TAG ('t','y','p','1')  /* Obsolete Apple Type1 font in SFNT container */
-  };
-
-  inline hb_tag_t get_tag (void) const { return u.tag; }
-
-  inline unsigned int get_face_count (void) const
-  {
-    switch (u.tag) {
-    case CFFTag:        /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:   return 1;
-    case TTCTag:        return u.ttcHeader.get_face_count ();
-//    case DFontTag:    return u.rfHeader.get_face_count ();
-    default:            return 0;
-    }
-  }
-  inline const OpenTypeFontFace& get_face (unsigned int i) const
-  {
-    switch (u.tag) {
-    /* Note: for non-collection SFNT data we ignore index.  This is because
-     * Apple dfont container is a container of SFNT's.  So each SFNT is a
-     * non-TTC, but the index is more than zero. */
-    case CFFTag:        /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:   return u.fontFace;
-    case TTCTag:        return u.ttcHeader.get_face (i);
-//    case DFontTag:    return u.rfHeader.get_face (i);
-    default:            return Null(OpenTypeFontFace);
-    }
-  }
-
-  inline bool serialize_single (hb_serialize_context_t *c,
-                                hb_tag_t sfnt_tag,
-                                Supplier<hb_tag_t> &tags,
-                                Supplier<hb_blob_t *> &blobs,
-                                unsigned int table_count)
-  {
-    TRACE_SERIALIZE (this);
-    assert (sfnt_tag != TTCTag);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    return_trace (u.fontFace.serialize (c, sfnt_tag, tags, blobs, table_count));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
-    switch (u.tag) {
-    case CFFTag:        /* All the non-collection tags */
-    case TrueTag:
-    case Typ1Tag:
-    case TrueTypeTag:   return_trace (u.fontFace.sanitize (c));
-    case TTCTag:        return_trace (u.ttcHeader.sanitize (c));
-//    case DFontTag:    return_trace (u.rfHeader.sanitize (c));
-    default:            return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  Tag                   tag;            /* 4-byte identifier. */
-  OpenTypeFontFace      fontFace;
-  TTCHeader             ttcHeader;
-  ResourceForkHeader    rfHeader;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (4, tag);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OPEN_FILE_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-file.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,525 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OPEN_FILE_HH
+#define HB_OPEN_FILE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-head-table.hh"
+
+
+namespace OT {
+
+
+/*
+ *
+ * The OpenType Font File
+ *
+ */
+
+
+/*
+ * Organization of an OpenType Font
+ */
+
+struct OpenTypeFontFile;
+struct OffsetTable;
+struct TTCHeader;
+
+
+typedef struct TableRecord
+{
+  int cmp (Tag t) const { return -t.cmp (tag); }
+
+  static int cmp (const void *pa, const void *pb)
+  {
+    const TableRecord *a = (const TableRecord *) pa;
+    const TableRecord *b = (const TableRecord *) pb;
+    return b->cmp (a->tag);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  Tag           tag;            /* 4-byte identifier. */
+  CheckSum      checkSum;       /* CheckSum for this table. */
+  Offset32      offset;         /* Offset from beginning of TrueType font
+                                 * file. */
+  HBUINT32      length;         /* Length of this table. */
+  public:
+  DEFINE_SIZE_STATIC (16);
+} OpenTypeTable;
+
+typedef struct OffsetTable
+{
+  friend struct OpenTypeFontFile;
+
+  unsigned int get_table_count () const { return tables.len; }
+  const TableRecord& get_table (unsigned int i) const
+  { return tables[i]; }
+  unsigned int get_table_tags (unsigned int  start_offset,
+                                      unsigned int *table_count, /* IN/OUT */
+                                      hb_tag_t     *table_tags /* OUT */) const
+  {
+    if (table_count)
+    {
+      if (start_offset >= tables.len)
+        *table_count = 0;
+      else
+        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
+
+      const TableRecord *sub_tables = tables.arrayZ + start_offset;
+      unsigned int count = *table_count;
+      for (unsigned int i = 0; i < count; i++)
+        table_tags[i] = sub_tables[i].tag;
+    }
+    return tables.len;
+  }
+  bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
+  {
+    Tag t;
+    t.set (tag);
+    return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+  }
+  const TableRecord& get_table_by_tag (hb_tag_t tag) const
+  {
+    unsigned int table_index;
+    find_table_index (tag, &table_index);
+    return get_table (table_index);
+  }
+
+  public:
+
+  template <typename item_t>
+  bool serialize (hb_serialize_context_t *c,
+                  hb_tag_t sfnt_tag,
+                  hb_array_t<item_t> items)
+  {
+    TRACE_SERIALIZE (this);
+    /* Alloc 12 for the OTHeader. */
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    /* Write sfntVersion (bytes 0..3). */
+    sfnt_version.set (sfnt_tag);
+    /* Take space for numTables, searchRange, entrySelector, RangeShift
+     * and the TableRecords themselves.  */
+    if (unlikely (!tables.serialize (c, items.length))) return_trace (false);
+
+    const char *dir_end = (const char *) c->head;
+    HBUINT32 *checksum_adjustment = nullptr;
+
+    /* Write OffsetTables, alloc for and write actual table blobs. */
+    for (unsigned int i = 0; i < tables.len; i++)
+    {
+      TableRecord &rec = tables.arrayZ[i];
+      hb_blob_t *blob = items[i].blob;
+      rec.tag.set (items[i].tag);
+      rec.length.set (hb_blob_get_length (blob));
+      rec.offset.serialize (c, this);
+
+      /* Allocate room for the table and copy it. */
+      char *start = (char *) c->allocate_size<void> (rec.length);
+      if (unlikely (!start)) {return false;}
+
+      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
+
+      /* 4-byte alignment. */
+      c->align (4);
+      const char *end = (const char *) c->head;
+
+      if (items[i].tag == HB_OT_TAG_head &&
+          (unsigned) (end - start) >= head::static_size)
+      {
+        head *h = (head *) start;
+        checksum_adjustment = &h->checkSumAdjustment;
+        checksum_adjustment->set (0);
+      }
+
+      rec.checkSum.set_for_data (start, end - start);
+    }
+
+    tables.qsort ();
+
+    if (checksum_adjustment)
+    {
+      CheckSum checksum;
+
+      /* The following line is a slower version of the following block. */
+      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
+      checksum.set_for_data (this, dir_end - (const char *) this);
+      for (unsigned int i = 0; i < items.length; i++)
+      {
+        TableRecord &rec = tables.arrayZ[i];
+        checksum.set (checksum + rec.checkSum);
+      }
+
+      checksum_adjustment->set (0xB1B0AFBAu - checksum);
+    }
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && tables.sanitize (c));
+  }
+
+  protected:
+  Tag           sfnt_version;   /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
+  BinSearchArrayOf<TableRecord>
+                tables;
+  public:
+  DEFINE_SIZE_ARRAY (12, tables);
+} OpenTypeFontFace;
+
+
+/*
+ * TrueType Collections
+ */
+
+struct TTCHeaderVersion1
+{
+  friend struct TTCHeader;
+
+  unsigned int get_face_count () const { return table.len; }
+  const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (table.sanitize (c, this));
+  }
+
+  protected:
+  Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
+  FixedVersion<>version;        /* Version of the TTC Header (1.0),
+                                 * 0x00010000u */
+  LArrayOf<LOffsetTo<OffsetTable> >
+                table;          /* Array of offsets to the OffsetTable for each font
+                                 * from the beginning of the file */
+  public:
+  DEFINE_SIZE_ARRAY (12, table);
+};
+
+struct TTCHeader
+{
+  friend struct OpenTypeFontFile;
+
+  private:
+
+  unsigned int get_face_count () const
+  {
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return u.version1.get_face_count ();
+    default:return 0;
+    }
+  }
+  const OpenTypeFontFace& get_face (unsigned int i) const
+  {
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return u.version1.get_face (i);
+    default:return Null(OpenTypeFontFace);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.header.version.sanitize (c))) return_trace (false);
+    switch (u.header.version.major) {
+    case 2: /* version 2 is compatible with version 1 */
+    case 1: return_trace (u.version1.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  struct {
+  Tag           ttcTag;         /* TrueType Collection ID string: 'ttcf' */
+  FixedVersion<>version;        /* Version of the TTC Header (1.0 or 2.0),
+                                 * 0x00010000u or 0x00020000u */
+  }                     header;
+  TTCHeaderVersion1     version1;
+  } u;
+};
+
+/*
+ * Mac Resource Fork
+ *
+ * http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
+ */
+
+struct ResourceRecord
+{
+  const OpenTypeFontFace & get_face (const void *data_base) const
+  { return CastR<OpenTypeFontFace> ((data_base+offset).arrayZ); }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                        const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  offset.sanitize (c, data_base) &&
+                  get_face (data_base).sanitize (c));
+  }
+
+  protected:
+  HBUINT16      id;             /* Resource ID. */
+  HBINT16       nameOffset;     /* Offset from beginning of resource name list
+                                 * to resource name, -1 means there is none. */
+  HBUINT8       attrs;          /* Resource attributes */
+  NNOffsetTo<LArrayOf<HBUINT8>, HBUINT24>
+                offset;         /* Offset from beginning of data block to
+                                 * data for this resource */
+  HBUINT32      reserved;       /* Reserved for handle to resource */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+#define HB_TAG_sfnt HB_TAG ('s','f','n','t')
+
+struct ResourceTypeRecord
+{
+  unsigned int get_resource_count () const
+  { return tag == HB_TAG_sfnt ? resCountM1 + 1 : 0; }
+
+  bool is_sfnt () const { return tag == HB_TAG_sfnt; }
+
+  const ResourceRecord& get_resource_record (unsigned int i,
+                                             const void *type_base) const
+  { return (type_base+resourcesZ).as_array (get_resource_count ())[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 const void *type_base,
+                 const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  resourcesZ.sanitize (c, type_base,
+                                       get_resource_count (),
+                                       data_base));
+  }
+
+  protected:
+  Tag           tag;            /* Resource type. */
+  HBUINT16      resCountM1;     /* Number of resources minus 1. */
+  NNOffsetTo<UnsizedArrayOf<ResourceRecord> >
+                resourcesZ;     /* Offset from beginning of resource type list
+                                 * to reference item list for this type. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct ResourceMap
+{
+  unsigned int get_face_count () const
+  {
+    unsigned int count = get_type_count ();
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ResourceTypeRecord& type = get_type_record (i);
+      if (type.is_sfnt ())
+        return type.get_resource_count ();
+    }
+    return 0;
+  }
+
+  const OpenTypeFontFace& get_face (unsigned int idx,
+                                    const void *data_base) const
+  {
+    unsigned int count = get_type_count ();
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const ResourceTypeRecord& type = get_type_record (i);
+      /* The check for idx < count is here because ResourceRecord is NOT null-safe.
+       * Because an offset of 0 there does NOT mean null. */
+      if (type.is_sfnt () && idx < type.get_resource_count ())
+        return type.get_resource_record (idx, &(this+typeList)).get_face (data_base);
+    }
+    return Null (OpenTypeFontFace);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *data_base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  typeList.sanitize (c, this,
+                                     &(this+typeList),
+                                     data_base));
+  }
+
+  private:
+  unsigned int get_type_count () const { return (this+typeList).lenM1 + 1; }
+
+  const ResourceTypeRecord& get_type_record (unsigned int i) const
+  { return (this+typeList)[i]; }
+
+  protected:
+  HBUINT8       reserved0[16];  /* Reserved for copy of resource header */
+  HBUINT32      reserved1;      /* Reserved for handle to next resource map */
+  HBUINT16      resreved2;      /* Reserved for file reference number */
+  HBUINT16      attrs;          /* Resource fork attribute */
+  NNOffsetTo<ArrayOfM1<ResourceTypeRecord> >
+                typeList;       /* Offset from beginning of map to
+                                 * resource type list */
+  Offset16      nameList;       /* Offset from beginning of map to
+                                 * resource name list */
+  public:
+  DEFINE_SIZE_STATIC (28);
+};
+
+struct ResourceForkHeader
+{
+  unsigned int get_face_count () const
+  { return (this+map).get_face_count (); }
+
+  const OpenTypeFontFace& get_face (unsigned int idx,
+                                    unsigned int *base_offset = nullptr) const
+  {
+    const OpenTypeFontFace &face = (this+map).get_face (idx, &(this+data));
+    if (base_offset)
+      *base_offset = (const char *) &face - (const char *) this;
+    return face;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  data.sanitize (c, this, dataLen) &&
+                  map.sanitize (c, this, &(this+data)));
+  }
+
+  protected:
+  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
+                data;           /* Offset from beginning of resource fork
+                                 * to resource data */
+  LNNOffsetTo<ResourceMap >
+                map;            /* Offset from beginning of resource fork
+                                 * to resource map */
+  HBUINT32      dataLen;        /* Length of resource data */
+  HBUINT32      mapLen;         /* Length of resource map */
+  public:
+  DEFINE_SIZE_STATIC (16);
+};
+
+/*
+ * OpenType Font File
+ */
+
+struct OpenTypeFontFile
+{
+  enum {
+    CFFTag              = HB_TAG ('O','T','T','O'), /* OpenType with Postscript outlines */
+    TrueTypeTag         = HB_TAG ( 0 , 1 , 0 , 0 ), /* OpenType with TrueType outlines */
+    TTCTag              = HB_TAG ('t','t','c','f'), /* TrueType Collection */
+    DFontTag            = HB_TAG ( 0 , 0 , 1 , 0 ), /* DFont Mac Resource Fork */
+    TrueTag             = HB_TAG ('t','r','u','e'), /* Obsolete Apple TrueType */
+    Typ1Tag             = HB_TAG ('t','y','p','1')  /* Obsolete Apple Type1 font in SFNT container */
+  };
+
+  hb_tag_t get_tag () const { return u.tag; }
+
+  unsigned int get_face_count () const
+  {
+    switch (u.tag) {
+    case CFFTag:        /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:   return 1;
+    case TTCTag:        return u.ttcHeader.get_face_count ();
+    case DFontTag:      return u.rfHeader.get_face_count ();
+    default:            return 0;
+    }
+  }
+  const OpenTypeFontFace& get_face (unsigned int i, unsigned int *base_offset = nullptr) const
+  {
+    if (base_offset)
+      *base_offset = 0;
+    switch (u.tag) {
+    /* Note: for non-collection SFNT data we ignore index.  This is because
+     * Apple dfont container is a container of SFNT's.  So each SFNT is a
+     * non-TTC, but the index is more than zero. */
+    case CFFTag:        /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:   return u.fontFace;
+    case TTCTag:        return u.ttcHeader.get_face (i);
+    case DFontTag:      return u.rfHeader.get_face (i, base_offset);
+    default:            return Null(OpenTypeFontFace);
+    }
+  }
+
+  template <typename item_t>
+  bool serialize_single (hb_serialize_context_t *c,
+                         hb_tag_t sfnt_tag,
+                         hb_array_t<item_t> items)
+  {
+    TRACE_SERIALIZE (this);
+    assert (sfnt_tag != TTCTag);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    return_trace (u.fontFace.serialize (c, sfnt_tag, items));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.tag.sanitize (c))) return_trace (false);
+    switch (u.tag) {
+    case CFFTag:        /* All the non-collection tags */
+    case TrueTag:
+    case Typ1Tag:
+    case TrueTypeTag:   return_trace (u.fontFace.sanitize (c));
+    case TTCTag:        return_trace (u.ttcHeader.sanitize (c));
+    case DFontTag:      return_trace (u.rfHeader.sanitize (c));
+    default:            return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  Tag                   tag;            /* 4-byte identifier. */
+  OpenTypeFontFace      fontFace;
+  TTCHeader             ttcHeader;
+  ResourceForkHeader    rfHeader;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (4, tag);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OPEN_FILE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1300 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OPEN_TYPE_PRIVATE_HH
-#define HB_OPEN_TYPE_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-blob-private.hh"
-#include "hb-face-private.hh"
-
-
-namespace OT {
-
-
-
-/*
- * Casts
- */
-
-/* Cast to struct T, reference to reference */
-template<typename Type, typename TObject>
-static inline const Type& CastR(const TObject &X)
-{ return reinterpret_cast<const Type&> (X); }
-template<typename Type, typename TObject>
-static inline Type& CastR(TObject &X)
-{ return reinterpret_cast<Type&> (X); }
-
-/* Cast to struct T, pointer to pointer */
-template<typename Type, typename TObject>
-static inline const Type* CastP(const TObject *X)
-{ return reinterpret_cast<const Type*> (X); }
-template<typename Type, typename TObject>
-static inline Type* CastP(TObject *X)
-{ return reinterpret_cast<Type*> (X); }
-
-/* StructAtOffset<T>(P,Ofs) returns the struct T& that is placed at memory
- * location pointed to by P plus Ofs bytes. */
-template<typename Type>
-static inline const Type& StructAtOffset(const void *P, unsigned int offset)
-{ return * reinterpret_cast<const Type*> ((const char *) P + offset); }
-template<typename Type>
-static inline Type& StructAtOffset(void *P, unsigned int offset)
-{ return * reinterpret_cast<Type*> ((char *) P + offset); }
-
-/* StructAfter<T>(X) returns the struct T& that is placed after X.
- * Works with X of variable size also.  X must implement get_size() */
-template<typename Type, typename TObject>
-static inline const Type& StructAfter(const TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-template<typename Type, typename TObject>
-static inline Type& StructAfter(TObject &X)
-{ return StructAtOffset<Type>(&X, X.get_size()); }
-
-
-
-/*
- * Size checking
- */
-
-/* Check _assertion in a method environment */
-#define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \
-  inline void _instance_assertion_on_line_##_line (void) const \
-  { \
-    static_assert ((_assertion), ""); \
-    ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
-  }
-# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
-# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
-
-/* Check that _code compiles in a method environment */
-#define _DEFINE_COMPILES_ASSERTION1(_line, _code) \
-  inline void _compiles_assertion_on_line_##_line (void) const \
-  { _code; }
-# define _DEFINE_COMPILES_ASSERTION0(_line, _code) _DEFINE_COMPILES_ASSERTION1 (_line, _code)
-# define DEFINE_COMPILES_ASSERTION(_code) _DEFINE_COMPILES_ASSERTION0 (__LINE__, _code)
-
-
-#define DEFINE_SIZE_STATIC(size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
-  static const unsigned int static_size = (size); \
-  static const unsigned int min_size = (size); \
-  inline unsigned int get_size (void) const { return (size); }
-
-#define DEFINE_SIZE_UNION(size, _member) \
-  DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_MIN(size) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) >= (size)); \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY(size, array) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (array[0])); \
-  DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
-  static const unsigned int min_size = (size)
-
-#define DEFINE_SIZE_ARRAY2(size, array1, array2) \
-  DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + sizeof (this->array1[0]) + sizeof (this->array2[0])); \
-  DEFINE_COMPILES_ASSERTION ((void) array1[0].static_size; (void) array2[0].static_size) \
-  static const unsigned int min_size = (size)
-
-
-
-/*
- * Dispatch
- */
-
-template <typename Context, typename Return, unsigned int MaxDebugDepth>
-struct hb_dispatch_context_t
-{
-  static const unsigned int max_debug_depth = MaxDebugDepth;
-  typedef Return return_t;
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format) { return true; }
-  static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
-};
-
-
-/*
- * Sanitize
- */
-
-/* This limits sanitizing time on really broken fonts. */
-#ifndef HB_SANITIZE_MAX_EDITS
-#define HB_SANITIZE_MAX_EDITS 32
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_FACTOR
-#define HB_SANITIZE_MAX_OPS_FACTOR 8
-#endif
-#ifndef HB_SANITIZE_MAX_OPS_MIN
-#define HB_SANITIZE_MAX_OPS_MIN 16384
-#endif
-
-struct hb_sanitize_context_t :
-       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
-{
-  inline hb_sanitize_context_t (void) :
-        debug_depth (0),
-        start (nullptr), end (nullptr),
-        writable (false), edit_count (0), max_ops (0),
-        blob (nullptr),
-        num_glyphs (0) {}
-
-  inline const char *get_name (void) { return "SANITIZE"; }
-  template <typename T, typename F>
-  inline bool may_dispatch (const T *obj, const F *format)
-  { return format->sanitize (this); }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
-  static return_t default_return_value (void) { return true; }
-  static return_t no_dispatch_return_value (void) { return false; }
-  bool stop_sublookup_iteration (const return_t r) const { return !r; }
-
-  inline void init (hb_blob_t *b)
-  {
-    this->blob = hb_blob_reference (b);
-    this->writable = false;
-  }
-
-  inline void start_processing (void)
-  {
-    this->start = hb_blob_get_data (this->blob, nullptr);
-    this->end = this->start + this->blob->length;
-    assert (this->start <= this->end); /* Must not overflow. */
-    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
-                         (unsigned) HB_SANITIZE_MAX_OPS_MIN);
-    this->edit_count = 0;
-    this->debug_depth = 0;
-
-    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
-                     "start [%p..%p] (%lu bytes)",
-                     this->start, this->end,
-                     (unsigned long) (this->end - this->start));
-  }
-
-  inline void end_processing (void)
-  {
-    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
-                     "end [%p..%p] %u edit requests",
-                     this->start, this->end, this->edit_count);
-
-    hb_blob_destroy (this->blob);
-    this->blob = nullptr;
-    this->start = this->end = nullptr;
-  }
-
-  inline bool check_range (const void *base, unsigned int len) const
-  {
-    const char *p = (const char *) base;
-    bool ok = this->max_ops-- > 0 &&
-              this->start <= p &&
-              p <= this->end &&
-              (unsigned int) (this->end - p) >= len;
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "check_range [%p..%p] (%d bytes) in [%p..%p] -> %s",
-       p, p + len, len,
-       this->start, this->end,
-       ok ? "OK" : "OUT-OF-RANGE");
-
-    return likely (ok);
-  }
-
-  inline bool check_array (const void *base, unsigned int record_size, unsigned int len) const
-  {
-    const char *p = (const char *) base;
-    bool overflows = _hb_unsigned_int_mul_overflows (len, record_size);
-    unsigned int array_size = record_size * len;
-    bool ok = !overflows && this->check_range (base, array_size);
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s",
-       p, p + (record_size * len), record_size, len, (unsigned int) array_size,
-       this->start, this->end,
-       overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE");
-
-    return likely (ok);
-  }
-
-  template <typename Type>
-  inline bool check_struct (const Type *obj) const
-  {
-    return likely (this->check_range (obj, obj->min_size));
-  }
-
-  inline bool may_edit (const void *base, unsigned int len)
-  {
-    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
-      return false;
-
-    const char *p = (const char *) base;
-    this->edit_count++;
-
-    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
-       this->edit_count,
-       p, p + len, len,
-       this->start, this->end,
-       this->writable ? "GRANTED" : "DENIED");
-
-    return this->writable;
-  }
-
-  template <typename Type, typename ValueType>
-  inline bool try_set (const Type *obj, const ValueType &v) {
-    if (this->may_edit (obj, obj->static_size)) {
-      const_cast<Type *> (obj)->set (v);
-      return true;
-    }
-    return false;
-  }
-
-  mutable unsigned int debug_depth;
-  const char *start, *end;
-  bool writable;
-  unsigned int edit_count;
-  mutable int max_ops;
-  hb_blob_t *blob;
-  unsigned int num_glyphs;
-};
-
-
-
-/* Template to sanitize an object. */
-template <typename Type>
-struct Sanitizer
-{
-  inline Sanitizer (void) {}
-
-  inline hb_blob_t *sanitize (hb_blob_t *blob) {
-    bool sane;
-
-    /* TODO is_sane() stuff */
-
-    c->init (blob);
-
-  retry:
-    DEBUG_MSG_FUNC (SANITIZE, c->start, "start");
-
-    c->start_processing ();
-
-    if (unlikely (!c->start)) {
-      c->end_processing ();
-      return blob;
-    }
-
-    Type *t = CastP<Type> (const_cast<char *> (c->start));
-
-    sane = t->sanitize (c);
-    if (sane) {
-      if (c->edit_count) {
-        DEBUG_MSG_FUNC (SANITIZE, c->start, "passed first round with %d edits; going for second round", c->edit_count);
-
-        /* sanitize again to ensure no toe-stepping */
-        c->edit_count = 0;
-        sane = t->sanitize (c);
-        if (c->edit_count) {
-          DEBUG_MSG_FUNC (SANITIZE, c->start, "requested %d edits in second round; FAILLING", c->edit_count);
-          sane = false;
-        }
-      }
-    } else {
-      unsigned int edit_count = c->edit_count;
-      if (edit_count && !c->writable) {
-        c->start = hb_blob_get_data_writable (blob, nullptr);
-        c->end = c->start + blob->length;
-
-        if (c->start) {
-          c->writable = true;
-          /* ok, we made it writable by relocating.  try again */
-          DEBUG_MSG_FUNC (SANITIZE, c->start, "retry");
-          goto retry;
-        }
-      }
-    }
-
-    c->end_processing ();
-
-    DEBUG_MSG_FUNC (SANITIZE, c->start, sane ? "PASSED" : "FAILED");
-    if (sane)
-    {
-      blob->lock ();
-      return blob;
-    }
-    else
-    {
-      hb_blob_destroy (blob);
-      return hb_blob_get_empty ();
-    }
-  }
-
-  inline void set_num_glyphs (unsigned int num_glyphs) { c->num_glyphs = num_glyphs; }
-
-  private:
-  hb_sanitize_context_t c[1];
-};
-
-
-
-/*
- * Serialize
- */
-
-
-struct hb_serialize_context_t
-{
-  inline hb_serialize_context_t (void *start_, unsigned int size)
-  {
-    this->start = (char *) start_;
-    this->end = this->start + size;
-
-    this->ran_out_of_room = false;
-    this->head = this->start;
-    this->debug_depth = 0;
-  }
-
-  template <typename Type>
-  inline Type *start_serialize (void)
-  {
-    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
-                     "start [%p..%p] (%lu bytes)",
-                     this->start, this->end,
-                     (unsigned long) (this->end - this->start));
-
-    return start_embed<Type> ();
-  }
-
-  inline void end_serialize (void)
-  {
-    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
-                     "end [%p..%p] serialized %d bytes; %s",
-                     this->start, this->end,
-                     (int) (this->head - this->start),
-                     this->ran_out_of_room ? "RAN OUT OF ROOM" : "did not ran out of room");
-
-  }
-
-  template <typename Type>
-  inline Type *copy (void)
-  {
-    assert (!this->ran_out_of_room);
-    unsigned int len = this->head - this->start;
-    void *p = malloc (len);
-    if (p)
-      memcpy (p, this->start, len);
-    return reinterpret_cast<Type *> (p);
-  }
-
-  template <typename Type>
-  inline Type *allocate_size (unsigned int size)
-  {
-    if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) {
-      this->ran_out_of_room = true;
-      return nullptr;
-    }
-    memset (this->head, 0, size);
-    char *ret = this->head;
-    this->head += size;
-    return reinterpret_cast<Type *> (ret);
-  }
-
-  template <typename Type>
-  inline Type *allocate_min (void)
-  {
-    return this->allocate_size<Type> (Type::min_size);
-  }
-
-  template <typename Type>
-  inline Type *start_embed (void)
-  {
-    Type *ret = reinterpret_cast<Type *> (this->head);
-    return ret;
-  }
-
-  template <typename Type>
-  inline Type *embed (const Type &obj)
-  {
-    unsigned int size = obj.get_size ();
-    Type *ret = this->allocate_size<Type> (size);
-    if (unlikely (!ret)) return nullptr;
-    memcpy (ret, obj, size);
-    return ret;
-  }
-
-  template <typename Type>
-  inline Type *extend_min (Type &obj)
-  {
-    unsigned int size = obj.min_size;
-    assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
-
-  template <typename Type>
-  inline Type *extend (Type &obj)
-  {
-    unsigned int size = obj.get_size ();
-    assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head);
-    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
-    return reinterpret_cast<Type *> (&obj);
-  }
-
-  inline void truncate (void *new_head)
-  {
-    assert (this->start < new_head && new_head <= this->head);
-    this->head = (char *) new_head;
-  }
-
-  unsigned int debug_depth;
-  char *start, *end, *head;
-  bool ran_out_of_room;
-};
-
-template <typename Type>
-struct Supplier
-{
-  inline Supplier (const Type *array, unsigned int len_, unsigned int stride_=sizeof(Type))
-  {
-    head = array;
-    len = len_;
-    stride = stride_;
-  }
-  inline const Type operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len)) return Type ();
-    return * (const Type *) (const void *) ((const char *) head + stride * i);
-  }
-
-  inline Supplier<Type> & operator += (unsigned int count)
-  {
-    if (unlikely (count > len))
-      count = len;
-    len -= count;
-    head = (const Type *) (const void *) ((const char *) head + stride * count);
-    return *this;
-  }
-
-  private:
-  inline Supplier (const Supplier<Type> &); /* Disallow copy */
-  inline Supplier<Type>& operator= (const Supplier<Type> &); /* Disallow copy */
-
-  unsigned int len;
-  unsigned int stride;
-  const Type *head;
-};
-
-
-/*
- *
- * The OpenType Font File: Data Types
- */
-
-
-/* "The following data types are used in the OpenType font file.
- *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
-
-/*
- * Int types
- */
-
-
-template <typename Type, int Bytes> struct BEInt;
-
-template <typename Type>
-struct BEInt<Type, 1>
-{
-  public:
-  inline void set (Type V)
-  {
-    v = V;
-  }
-  inline operator Type (void) const
-  {
-    return v;
-  }
-  private: uint8_t v;
-};
-template <typename Type>
-struct BEInt<Type, 2>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >>  8) & 0xFF;
-    v[1] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] <<  8)
-         + (v[1]      );
-  }
-  private: uint8_t v[2];
-};
-template <typename Type>
-struct BEInt<Type, 3>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >> 16) & 0xFF;
-    v[1] = (V >>  8) & 0xFF;
-    v[2] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] << 16)
-         + (v[1] <<  8)
-         + (v[2]      );
-  }
-  private: uint8_t v[3];
-};
-template <typename Type>
-struct BEInt<Type, 4>
-{
-  public:
-  inline void set (Type V)
-  {
-    v[0] = (V >> 24) & 0xFF;
-    v[1] = (V >> 16) & 0xFF;
-    v[2] = (V >>  8) & 0xFF;
-    v[3] = (V      ) & 0xFF;
-  }
-  inline operator Type (void) const
-  {
-    return (v[0] << 24)
-         + (v[1] << 16)
-         + (v[2] <<  8)
-         + (v[3]      );
-  }
-  private: uint8_t v[4];
-};
-
-/* Integer types in big-endian order and no alignment requirement */
-template <typename Type, unsigned int Size>
-struct IntType
-{
-  inline void set (Type i) { v.set (i); }
-  inline operator Type(void) const { return v; }
-  inline bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
-  inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
-  static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
-  template <typename Type2>
-  inline int cmp (Type2 a) const
-  {
-    Type b = v;
-    if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
-      return (int) a - (int) b;
-    else
-      return a < b ? -1 : a == b ? 0 : +1;
-  }
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  BEInt<Type, Size> v;
-  public:
-  DEFINE_SIZE_STATIC (Size);
-};
-
-typedef IntType<uint8_t,  1> HBUINT8;   /* 8-bit unsigned integer. */
-typedef IntType<int8_t,   1> HBINT8;    /* 8-bit signed integer. */
-typedef IntType<uint16_t, 2> HBUINT16;  /* 16-bit unsigned integer. */
-typedef IntType<int16_t,  2> HBINT16;   /* 16-bit signed integer. */
-typedef IntType<uint32_t, 4> HBUINT32;  /* 32-bit unsigned integer. */
-typedef IntType<int32_t,  4> HBINT32;   /* 32-bit signed integer. */
-typedef IntType<uint32_t, 3> HBUINT24;  /* 24-bit unsigned integer. */
-
-/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
-typedef HBINT16 FWORD;
-
-/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
-typedef HBUINT16 UFWORD;
-
-/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
-struct F2DOT14 : HBINT16
-{
-  // 16384 means 1<<14
-  inline float to_float (void) const { return ((int32_t) v) / 16384.f; }
-  inline void set_float (float f) { v.set (round (f * 16384.f)); }
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-/* 32-bit signed fixed-point number (16.16). */
-struct Fixed : HBINT32
-{
-  // 65536 means 1<<16
-  inline float to_float (void) const { return ((int32_t) v) / 65536.f; }
-  inline void set_float (float f) { v.set (round (f * 65536.f)); }
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-/* Date represented in number of seconds since 12:00 midnight, January 1,
- * 1904. The value is represented as a signed 64-bit integer. */
-struct LONGDATETIME
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this)));
-  }
-  protected:
-  HBINT32 major;
-  HBUINT32 minor;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-/* Array of four uint8s (length = 32 bits) used to identify a script, language
- * system, feature, or baseline */
-struct Tag : HBUINT32
-{
-  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
-  inline operator const char* (void) const { return reinterpret_cast<const char *> (&this->v); }
-  inline operator char* (void) { return reinterpret_cast<char *> (&this->v); }
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-DEFINE_NULL_DATA (OT, Tag, "    ");
-
-/* Glyph index number, same as uint16 (length = 16 bits) */
-typedef HBUINT16 GlyphID;
-
-/* Name-table index, same as uint16 (length = 16 bits) */
-typedef HBUINT16 NameID;
-
-/* Script/language-system/feature index */
-struct Index : HBUINT16 {
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
-};
-DEFINE_NULL_DATA (OT, Index, "\xff\xff");
-
-/* Offset, Null offset = 0 */
-template <typename Type>
-struct Offset : Type
-{
-  inline bool is_null (void) const { return 0 == *this; }
-
-  inline void *serialize (hb_serialize_context_t *c, const void *base)
-  {
-    void *t = c->start_embed<void> ();
-    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
-    return t;
-  }
-
-  public:
-  DEFINE_SIZE_STATIC (sizeof(Type));
-};
-
-typedef Offset<HBUINT16> Offset16;
-typedef Offset<HBUINT32> Offset32;
-
-
-/* CheckSum */
-struct CheckSum : HBUINT32
-{
-  /* This is reference implementation from the spec. */
-  static inline uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
-  {
-    uint32_t Sum = 0L;
-    assert (0 == (Length & 3));
-    const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
-
-    while (Table < EndPtr)
-      Sum += *Table++;
-    return Sum;
-  }
-
-  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
-  inline void set_for_data (const void *data, unsigned int length)
-  { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
-/*
- * Version Numbers
- */
-
-template <typename FixedType=HBUINT16>
-struct FixedVersion
-{
-  inline uint32_t to_int (void) const { return (major << (sizeof(FixedType) * 8)) + minor; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  FixedType major;
-  FixedType minor;
-  public:
-  DEFINE_SIZE_STATIC (2 * sizeof(FixedType));
-};
-
-
-
-/*
- * Template subclasses of Offset that do the dereferencing.
- * Use: (base+offset)
- */
-
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetTo : Offset<OffsetType>
-{
-  inline const Type& operator () (const void *base) const
-  {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Null(Type);
-    return StructAtOffset<const Type> (base, offset);
-  }
-  inline Type& operator () (void *base) const
-  {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Crap(Type);
-    return StructAtOffset<Type> (base, offset);
-  }
-
-  inline Type& serialize (hb_serialize_context_t *c, const void *base)
-  {
-    return * (Type *) Offset<OffsetType>::serialize (c, base);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
-    const Type &obj = StructAtOffset<Type> (base, offset);
-    return_trace (likely (obj.sanitize (c)) || neuter (c));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
-    const Type &obj = StructAtOffset<Type> (base, offset);
-    return_trace (likely (obj.sanitize (c, user_data)) || neuter (c));
-  }
-
-  /* Set the offset to Null */
-  inline bool neuter (hb_sanitize_context_t *c) const {
-    return c->try_set (this, 0);
-  }
-  DEFINE_SIZE_STATIC (sizeof(OffsetType));
-};
-template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
-template <typename Base, typename OffsetType, typename Type>
-static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-template <typename Base, typename OffsetType, typename Type>
-static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-
-
-/*
- * Array Types
- */
-
-
-/* TODO Use it in ArrayOf, HeadlessArrayOf, and other places around the code base?? */
-template <typename Type>
-struct UnsizedArrayOf
-{
-  inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; }
-  inline Type& operator [] (unsigned int i) { return arrayZ[i]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base)))
-        return_trace (false);
-    return_trace (true);
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-        return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
-  }
-
-  public:
-  Type  arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (0, arrayZ);
-};
-
-/* Unsized array of offset's */
-template <typename Type, typename OffsetType>
-struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType> > {};
-
-/* Unsized array of offsets relative to the beginning of the array itself. */
-template <typename Type, typename OffsetType>
-struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType>
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    return this+this->arrayZ[i];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this)));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType>::sanitize (c, count, this, user_data)));
-  }
-};
-
-
-/* An array with a number of elements. */
-template <typename Type, typename LenType=HBUINT16>
-struct ArrayOf
-{
-  const Type *sub_array (unsigned int start_offset, unsigned int *pcount /* IN/OUT */) const
-  {
-    unsigned int count = len;
-    if (unlikely (start_offset > count))
-      count = 0;
-    else
-      count -= start_offset;
-    count = MIN (count, *pcount);
-    *pcount = count;
-    return arrayZ + start_offset;
-  }
-
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len)) return Null(Type);
-    return arrayZ[i];
-  }
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len)) return Crap(Type);
-    return arrayZ[i];
-  }
-  inline unsigned int get_size (void) const
-  { return len.static_size + len * Type::static_size; }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!c->extend (*this))) return_trace (false);
-    return_trace (true);
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<Type> &items,
-                         unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!serialize (c, items_len))) return_trace (false);
-    for (unsigned int i = 0; i < items_len; i++)
-      arrayZ[i] = items[i];
-    items += items_len;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base)))
-        return_trace (false);
-    return_trace (true);
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-        return_trace (false);
-    return_trace (true);
-  }
-
-  template <typename SearchType>
-  inline int lsearch (const SearchType &x) const
-  {
-    unsigned int count = len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!this->arrayZ[i].cmp (x))
-        return i;
-    return -1;
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) && c->check_array (arrayZ, Type::static_size, len));
-  }
-
-  public:
-  LenType len;
-  Type arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
-};
-template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
-typedef ArrayOf<HBUINT8, HBUINT8> PString;
-
-/* Array of Offset's */
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetArrayOf : ArrayOf<OffsetTo<Type, OffsetType> > {};
-
-/* Array of offsets relative to the beginning of the array itself. */
-template <typename Type>
-struct OffsetListOf : OffsetArrayOf<Type>
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= this->len)) return Null(Type);
-    return this+this->arrayZ[i];
-  }
-  inline const Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= this->len)) return Crap(Type);
-    return this+this->arrayZ[i];
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
-  }
-  template <typename T>
-  inline bool sanitize (hb_sanitize_context_t *c, T user_data) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
-  }
-};
-
-
-/* An array starting at second element. */
-template <typename Type, typename LenType=HBUINT16>
-struct HeadlessArrayOf
-{
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len || !i)) return Null(Type);
-    return arrayZ[i-1];
-  }
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len || !i)) return Crap(Type);
-    return arrayZ[i-1];
-  }
-  inline unsigned int get_size (void) const
-  { return len.static_size + (len ? len - 1 : 0) * Type::static_size; }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<Type> &items,
-                         unsigned int items_len)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    len.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!items_len)) return_trace (true);
-    if (unlikely (!c->extend (*this))) return_trace (false);
-    for (unsigned int i = 0; i < items_len - 1; i++)
-      arrayZ[i] = items[i];
-    items += items_len - 1;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-
-    /* Note: for structs that do not reference other structs,
-     * we do not need to call their sanitize() as we already did
-     * a bound check on the aggregate array size.  We just include
-     * a small unreachable expression to make sure the structs
-     * pointed to do have a simple sanitize(), ie. they do not
-     * reference other structs via offsets.
-     */
-    (void) (false && arrayZ[0].sanitize (c));
-
-    return_trace (true);
-  }
-
-  private:
-  inline bool sanitize_shallow (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (len.sanitize (c) &&
-                  (!len || c->check_array (arrayZ, Type::static_size, len - 1)));
-  }
-
-  public:
-  LenType len;
-  Type arrayZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
-};
-
-
-/*
- * An array with sorted elements.  Supports binary searching.
- */
-template <typename Type, typename LenType=HBUINT16>
-struct SortedArrayOf : ArrayOf<Type, LenType>
-{
-  template <typename SearchType>
-  inline int bsearch (const SearchType &x) const
-  {
-    /* Hand-coded bsearch here since this is in the hot inner loop. */
-    const Type *arr = this->arrayZ;
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = arr[mid].cmp (x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-        return mid;
-    }
-    return -1;
-  }
-};
-
-/*
- * Binary-search arrays
- */
-
-struct BinSearchHeader
-{
-  inline operator uint32_t (void) const { return len; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline void set (unsigned int v)
-  {
-    len.set (v);
-    assert (len == v);
-    entrySelector.set (MAX (1u, _hb_bit_storage (v)) - 1);
-    searchRange.set (16 * (1u << entrySelector));
-    rangeShift.set (v * 16 > searchRange
-                    ? 16 * v - searchRange
-                    : 0);
-  }
-
-  protected:
-  HBUINT16      len;
-  HBUINT16      searchRange;
-  HBUINT16      entrySelector;
-  HBUINT16      rangeShift;
-
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-template <typename Type>
-struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader> {};
-
-
-/* Lazy struct and blob loaders. */
-
-/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
-template <typename T>
-struct hb_lazy_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    instance = nullptr;
-  }
-
-  inline void fini (void)
-  {
-    if (instance && instance != &Null(T))
-    {
-      instance->fini();
-      free (instance);
-    }
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    T *p = (T *) hb_atomic_ptr_get (&instance);
-    if (unlikely (!p))
-    {
-      p = (T *) calloc (1, sizeof (T));
-      if (unlikely (!p))
-        p = const_cast<T *> (&Null(T));
-      else
-        p->init (face);
-      if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&instance), nullptr, p)))
-      {
-        if (p != &Null(T))
-          p->fini ();
-        goto retry;
-      }
-    }
-    return p;
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get ();
-  }
-
-  private:
-  hb_face_t *face;
-  T *instance;
-};
-
-/* Logic is shared between hb_lazy_loader_t and hb_table_lazy_loader_t */
-template <typename T>
-struct hb_table_lazy_loader_t
-{
-  inline void init (hb_face_t *face_)
-  {
-    face = face_;
-    blob = nullptr;
-  }
-
-  inline void fini (void)
-  {
-    hb_blob_destroy (blob);
-  }
-
-  inline const T* get (void) const
-  {
-  retry:
-    hb_blob_t *blob_ = (hb_blob_t *) hb_atomic_ptr_get (&blob);
-    if (unlikely (!blob_))
-    {
-      blob_ = OT::Sanitizer<T>().sanitize (face->reference_table (T::tableTag));
-      if (!hb_atomic_ptr_cmpexch (&blob, nullptr, blob_))
-      {
-        hb_blob_destroy (blob_);
-        goto retry;
-      }
-      blob = blob_;
-    }
-    return blob_->as<T> ();
-  }
-
-  inline const T* operator-> (void) const
-  {
-    return get();
-  }
-
-  private:
-  hb_face_t *face;
-  mutable hb_blob_t *blob;
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OPEN_TYPE_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,1008 @@
+/*
+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OPEN_TYPE_HH
+#define HB_OPEN_TYPE_HH
+
+#include "hb.hh"
+#include "hb-blob.hh"
+#include "hb-face.hh"
+#include "hb-machinery.hh"
+#include "hb-subset.hh"
+
+
+namespace OT {
+
+
+/*
+ *
+ * The OpenType Font File: Data Types
+ */
+
+
+/* "The following data types are used in the OpenType font file.
+ *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
+
+/*
+ * Int types
+ */
+
+template <bool is_signed> struct hb_signedness_int;
+template <> struct hb_signedness_int<false> { typedef unsigned int value; };
+template <> struct hb_signedness_int<true>  { typedef   signed int value; };
+
+/* Integer types in big-endian order and no alignment requirement */
+template <typename Type, unsigned int Size>
+struct IntType
+{
+  typedef Type type;
+  typedef typename hb_signedness_int<hb_is_signed<Type>::value>::value wide_type;
+
+  void set (wide_type i) { v.set (i); }
+  operator wide_type () const { return v; }
+  bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
+  bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
+  static int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
+  template <typename Type2>
+  int cmp (Type2 a) const
+  {
+    Type b = v;
+    if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
+      return (int) a - (int) b;
+    else
+      return a < b ? -1 : a == b ? 0 : +1;
+  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+  protected:
+  BEInt<Type, Size> v;
+  public:
+  DEFINE_SIZE_STATIC (Size);
+};
+
+typedef IntType<uint8_t,  1> HBUINT8;   /* 8-bit unsigned integer. */
+typedef IntType<int8_t,   1> HBINT8;    /* 8-bit signed integer. */
+typedef IntType<uint16_t, 2> HBUINT16;  /* 16-bit unsigned integer. */
+typedef IntType<int16_t,  2> HBINT16;   /* 16-bit signed integer. */
+typedef IntType<uint32_t, 4> HBUINT32;  /* 32-bit unsigned integer. */
+typedef IntType<int32_t,  4> HBINT32;   /* 32-bit signed integer. */
+/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
+ * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
+typedef IntType<uint32_t, 3> HBUINT24;  /* 24-bit unsigned integer. */
+
+/* 16-bit signed integer (HBINT16) that describes a quantity in FUnits. */
+typedef HBINT16 FWORD;
+
+/* 32-bit signed integer (HBINT32) that describes a quantity in FUnits. */
+typedef HBINT32 FWORD32;
+
+/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
+typedef HBUINT16 UFWORD;
+
+/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
+struct F2DOT14 : HBINT16
+{
+  // 16384 means 1<<14
+  float to_float () const  { return ((int32_t) v) / 16384.f; }
+  void set_float (float f) { v.set (round (f * 16384.f)); }
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+/* 32-bit signed fixed-point number (16.16). */
+struct Fixed : HBINT32
+{
+  // 65536 means 1<<16
+  float to_float () const  { return ((int32_t) v) / 65536.f; }
+  void set_float (float f) { v.set (round (f * 65536.f)); }
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* Date represented in number of seconds since 12:00 midnight, January 1,
+ * 1904. The value is represented as a signed 64-bit integer. */
+struct LONGDATETIME
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+  protected:
+  HBINT32 major;
+  HBUINT32 minor;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+/* Array of four uint8s (length = 32 bits) used to identify a script, language
+ * system, feature, or baseline */
+struct Tag : HBUINT32
+{
+  /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
+  operator const char* () const { return reinterpret_cast<const char *> (&this->v); }
+  operator char* ()             { return reinterpret_cast<char *> (&this->v); }
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* Glyph index number, same as uint16 (length = 16 bits) */
+typedef HBUINT16 GlyphID;
+
+/* Script/language-system/feature index */
+struct Index : HBUINT16 {
+  static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFu;
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
+
+typedef Index NameID;
+
+/* Offset, Null offset = 0 */
+template <typename Type, bool has_null=true>
+struct Offset : Type
+{
+  typedef Type type;
+
+  bool is_null () const { return has_null && 0 == *this; }
+
+  void *serialize (hb_serialize_context_t *c, const void *base)
+  {
+    void *t = c->start_embed<void> ();
+    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
+    return t;
+  }
+
+  public:
+  DEFINE_SIZE_STATIC (sizeof (Type));
+};
+
+typedef Offset<HBUINT16> Offset16;
+typedef Offset<HBUINT32> Offset32;
+
+
+/* CheckSum */
+struct CheckSum : HBUINT32
+{
+  /* This is reference implementation from the spec. */
+  static uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
+  {
+    uint32_t Sum = 0L;
+    assert (0 == (Length & 3));
+    const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
+
+    while (Table < EndPtr)
+      Sum += *Table++;
+    return Sum;
+  }
+
+  /* Note: data should be 4byte aligned and have 4byte padding at the end. */
+  void set_for_data (const void *data, unsigned int length)
+  { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+
+/*
+ * Version Numbers
+ */
+
+template <typename FixedType=HBUINT16>
+struct FixedVersion
+{
+  uint32_t to_int () const { return (major << (sizeof (FixedType) * 8)) + minor; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  FixedType major;
+  FixedType minor;
+  public:
+  DEFINE_SIZE_STATIC (2 * sizeof (FixedType));
+};
+
+
+/*
+ * Template subclasses of Offset that do the dereferencing.
+ * Use: (base+offset)
+ */
+
+template <typename Type, bool has_null>
+struct _hb_has_null
+{
+  static const Type *get_null () { return nullptr; }
+  static Type *get_crap ()       { return nullptr; }
+};
+template <typename Type>
+struct _hb_has_null<Type, true>
+{
+  static const Type *get_null () { return &Null(Type); }
+  static Type *get_crap ()       { return &Crap(Type); }
+};
+
+template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
+struct OffsetTo : Offset<OffsetType, has_null>
+{
+  const Type& operator () (const void *base) const
+  {
+    if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_null ();
+    return StructAtOffset<const Type> (base, *this);
+  }
+  Type& operator () (void *base) const
+  {
+    if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_crap ();
+    return StructAtOffset<Type> (base, *this);
+  }
+
+  Type& serialize (hb_serialize_context_t *c, const void *base)
+  {
+    return * (Type *) Offset<OffsetType>::serialize (c, base);
+  }
+
+  template <typename T>
+  void serialize_subset (hb_subset_context_t *c, const T &src, const void *base)
+  {
+    if (&src == &Null (T))
+    {
+      this->set (0);
+      return;
+    }
+    serialize (c->serializer, base);
+    if (!src.subset (c))
+      this->set (0);
+  }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+    if (unlikely (this->is_null ())) return_trace (true);
+    if (unlikely (!c->check_range (base, *this))) return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                  (this->is_null () ||
+                   StructAtOffset<Type> (base, *this).sanitize (c) ||
+                   neuter (c)));
+  }
+  template <typename T1>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                  (this->is_null () ||
+                   StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
+                   neuter (c)));
+  }
+  template <typename T1, typename T2>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                  (this->is_null () ||
+                   StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
+                   neuter (c)));
+  }
+  template <typename T1, typename T2, typename T3>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (sanitize_shallow (c, base) &&
+                  (this->is_null () ||
+                   StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
+                   neuter (c)));
+  }
+
+  /* Set the offset to Null */
+  bool neuter (hb_sanitize_context_t *c) const
+  {
+    if (!has_null) return false;
+    return c->try_set (this, 0);
+  }
+  DEFINE_SIZE_STATIC (sizeof (OffsetType));
+};
+/* Partial specializations. */
+template <typename Type,                               bool has_null=true> struct   LOffsetTo : OffsetTo<Type, HBUINT32,   has_null> {};
+template <typename Type, typename OffsetType=HBUINT16                    > struct  NNOffsetTo : OffsetTo<Type, OffsetType, false> {};
+template <typename Type                                                  > struct LNNOffsetTo : OffsetTo<Type, HBUINT32,   false> {};
+
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
+
+
+/*
+ * Array Types
+ */
+
+template <typename Type>
+struct UnsizedArrayOf
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    const Type *p = &arrayZ[i];
+    if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */
+    return *p;
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    Type *p = &arrayZ[i];
+    if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */
+    return *p;
+  }
+
+  unsigned int get_size (unsigned int len) const
+  { return len * Type::static_size; }
+
+  template <typename T> operator T * () { return arrayZ; }
+  template <typename T> operator const T * () const { return arrayZ; }
+  hb_array_t<Type> as_array (unsigned int len)
+  { return hb_array (arrayZ, len); }
+  hb_array_t<const Type> as_array (unsigned int len) const
+  { return hb_array (arrayZ, len); }
+  operator hb_array_t<Type> ()             { return as_array (); }
+  operator hb_array_t<const Type> () const { return as_array (); }
+
+  template <typename T>
+  Type &lsearch (unsigned int len, const T &x, Type &not_found = Crap (Type))
+  { return *as_array (len).lsearch (x, &not_found); }
+  template <typename T>
+  const Type &lsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array (len).lsearch (x, &not_found); }
+
+  void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array (len).qsort (start, end); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base)))
+        return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+        return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_array (arrayZ, count));
+  }
+
+  public:
+  Type          arrayZ[VAR];
+  public:
+  DEFINE_SIZE_UNBOUNDED (0);
+};
+
+/* Unsized array of offset's */
+template <typename Type, typename OffsetType, bool has_null=true>
+struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null> > {};
+
+/* Unsized array of offsets relative to the beginning of the array itself. */
+template <typename Type, typename OffsetType, bool has_null=true>
+struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
+{
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
+    if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
+    return this+*p;
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
+    if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
+    return this+*p;
+  }
+
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this)));
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this, user_data)));
+  }
+};
+
+/* An array with sorted elements.  Supports binary searching. */
+template <typename Type>
+struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
+{
+  hb_sorted_array_t<Type> as_array (unsigned int len)
+  { return hb_sorted_array (this->arrayZ, len); }
+  hb_sorted_array_t<const Type> as_array (unsigned int len) const
+  { return hb_sorted_array (this->arrayZ, len); }
+  operator hb_sorted_array_t<Type> ()             { return as_array (); }
+  operator hb_sorted_array_t<const Type> () const { return as_array (); }
+
+  template <typename T>
+  Type &bsearch (unsigned int len, const T &x, Type &not_found = Crap (Type))
+  { return *as_array (len).bsearch (x, &not_found); }
+  template <typename T>
+  const Type &bsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array (len).bsearch (x, &not_found); }
+  template <typename T>
+  bool bfind (unsigned int len, const T &x, unsigned int *i = nullptr,
+                     hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                     unsigned int to_store = (unsigned int) -1) const
+  { return as_array (len).bfind (x, i, not_found, to_store); }
+};
+
+
+/* An array with a number of elements. */
+template <typename Type, typename LenType=HBUINT16>
+struct ArrayOf
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= len)) return Null (Type);
+    return arrayZ[i];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= len)) return Crap (Type);
+    return arrayZ[i];
+  }
+
+  unsigned int get_size () const
+  { return len.static_size + len * Type::static_size; }
+
+  hb_array_t<Type> as_array ()
+  { return hb_array (arrayZ, len); }
+  hb_array_t<const Type> as_array () const
+  { return hb_array (arrayZ, len); }
+  operator hb_array_t<Type> (void)             { return as_array (); }
+  operator hb_array_t<const Type> (void) const { return as_array (); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    len.set (items_len); /* TODO(serialize) Overflow? */
+    if (unlikely (!c->extend (*this))) return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool serialize (hb_serialize_context_t *c, hb_array_t<const T> items)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!serialize (c, items.length))) return_trace (false);
+    for (unsigned int i = 0; i < items.length; i++)
+      hb_assign (arrayZ[i], items[i]);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base)))
+        return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+        return_trace (false);
+    return_trace (true);
+  }
+
+  template <typename T>
+  Type &lsearch (const T &x, Type &not_found = Crap (Type))
+  { return *as_array ().lsearch (x, &not_found); }
+  template <typename T>
+  const Type &lsearch (const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array ().lsearch (x, &not_found); }
+
+  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array ().qsort (start, end); }
+
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (len.sanitize (c) && c->check_array (arrayZ, len));
+  }
+
+  public:
+  LenType       len;
+  Type          arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
+typedef ArrayOf<HBUINT8, HBUINT8> PString;
+
+/* Array of Offset's */
+template <typename Type>
+struct OffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT16> > {};
+template <typename Type>
+struct LOffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT32> > {};
+template <typename Type>
+struct LOffsetLArrayOf : ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32> {};
+
+/* Array of offsets relative to the beginning of the array itself. */
+template <typename Type>
+struct OffsetListOf : OffsetArrayOf<Type>
+{
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= this->len)) return Null (Type);
+    return this+this->arrayZ[i];
+  }
+  const Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= this->len)) return Crap (Type);
+    return this+this->arrayZ[i];
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct OffsetListOf<Type> *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    unsigned int count = this->len;
+    for (unsigned int i = 0; i < count; i++)
+      out->arrayZ[i].serialize_subset (c, (*this)[i], out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
+  }
+};
+
+/* An array starting at second element. */
+template <typename Type, typename LenType=HBUINT16>
+struct HeadlessArrayOf
+{
+  static constexpr unsigned item_size = Type::static_size;
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (HeadlessArrayOf, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= lenP1 || !i)) return Null (Type);
+    return arrayZ[i-1];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= lenP1 || !i)) return Crap (Type);
+    return arrayZ[i-1];
+  }
+  unsigned int get_size () const
+  { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const Type> items)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    lenP1.set (items.length + 1); /* TODO(serialize) Overflow? */
+    if (unlikely (!c->extend (*this))) return_trace (false);
+    for (unsigned int i = 0; i < items.length; i++)
+      arrayZ[i] = items[i];
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && arrayZ[0].sanitize (c));
+
+    return_trace (true);
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (lenP1.sanitize (c) &&
+                  (!lenP1 || c->check_array (arrayZ, lenP1 - 1)));
+  }
+
+  public:
+  LenType       lenP1;
+  Type          arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+
+/* An array storing length-1. */
+template <typename Type, typename LenType=HBUINT16>
+struct ArrayOfM1
+{
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOfM1, Type, LenType);
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i > lenM1)) return Null (Type);
+    return arrayZ[i];
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i > lenM1)) return Crap (Type);
+    return arrayZ[i];
+  }
+  unsigned int get_size () const
+  { return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
+
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = lenM1 + 1;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
+        return_trace (false);
+    return_trace (true);
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (lenM1.sanitize (c) &&
+                  (c->check_array (arrayZ, lenM1 + 1)));
+  }
+
+  public:
+  LenType       lenM1;
+  Type          arrayZ[VAR];
+  public:
+  DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
+};
+
+/* An array with sorted elements.  Supports binary searching. */
+template <typename Type, typename LenType=HBUINT16>
+struct SortedArrayOf : ArrayOf<Type, LenType>
+{
+  hb_sorted_array_t<Type> as_array ()
+  { return hb_sorted_array (this->arrayZ, this->len); }
+  hb_sorted_array_t<const Type> as_array () const
+  { return hb_sorted_array (this->arrayZ, this->len); }
+  operator hb_sorted_array_t<Type> ()             { return as_array (); }
+  operator hb_sorted_array_t<const Type> () const { return as_array (); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  template <typename T>
+  Type &bsearch (const T &x, Type &not_found = Crap (Type))
+  { return *as_array ().bsearch (x, &not_found); }
+  template <typename T>
+  const Type &bsearch (const T &x, const Type &not_found = Null (Type)) const
+  { return *as_array ().bsearch (x, &not_found); }
+  template <typename T>
+  bool bfind (const T &x, unsigned int *i = nullptr,
+                     hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                     unsigned int to_store = (unsigned int) -1) const
+  { return as_array ().bfind (x, i, not_found, to_store); }
+};
+
+/*
+ * Binary-search arrays
+ */
+
+template <typename LenType=HBUINT16>
+struct BinSearchHeader
+{
+  operator uint32_t () const { return len; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  void set (unsigned int v)
+  {
+    len.set (v);
+    assert (len == v);
+    entrySelector.set (MAX (1u, hb_bit_storage (v)) - 1);
+    searchRange.set (16 * (1u << entrySelector));
+    rangeShift.set (v * 16 > searchRange
+                    ? 16 * v - searchRange
+                    : 0);
+  }
+
+  protected:
+  LenType       len;
+  LenType       searchRange;
+  LenType       entrySelector;
+  LenType       rangeShift;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+template <typename Type, typename LenType=HBUINT16>
+struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader<LenType> > {};
+
+
+struct VarSizedBinSearchHeader
+{
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16      unitSize;       /* Size of a lookup unit for this search in bytes. */
+  HBUINT16      nUnits;         /* Number of units of the preceding size to be searched. */
+  HBUINT16      searchRange;    /* The value of unitSize times the largest power of 2
+                                 * that is less than or equal to the value of nUnits. */
+  HBUINT16      entrySelector;  /* The log base 2 of the largest power of 2 less than
+                                 * or equal to the value of nUnits. */
+  HBUINT16      rangeShift;     /* The value of unitSize times the difference of the
+                                 * value of nUnits minus the largest power of 2 less
+                                 * than or equal to the value of nUnits. */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+template <typename Type>
+struct VarSizedBinSearchArrayOf
+{
+  static constexpr unsigned item_size = Type::static_size;
+
+  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
+
+  bool last_is_terminator () const
+  {
+    if (unlikely (!header.nUnits)) return false;
+
+    /* Gah.
+     *
+     * "The number of termination values that need to be included is table-specific.
+     * The value that indicates binary search termination is 0xFFFF." */
+    const HBUINT16 *words = &StructAtOffset<HBUINT16> (&bytesZ, (header.nUnits - 1) * header.unitSize);
+    unsigned int count = Type::TerminationWordCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (words[i] != 0xFFFFu)
+        return false;
+    return true;
+  }
+
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= get_length ())) return Null (Type);
+    return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
+  }
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= get_length ())) return Crap (Type);
+    return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
+  }
+  unsigned int get_length () const
+  { return header.nUnits - last_is_terminator (); }
+  unsigned int get_size () const
+  { return header.static_size + header.nUnits * header.unitSize; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size.  We just include
+     * a small unreachable expression to make sure the structs
+     * pointed to do have a simple sanitize(), ie. they do not
+     * reference other structs via offsets.
+     */
+    (void) (false && StructAtOffset<Type> (&bytesZ, 0).sanitize (c));
+
+    return_trace (true);
+  }
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = get_length ();
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!(*this)[i].sanitize (c, base)))
+        return_trace (false);
+    return_trace (true);
+  }
+  template <typename T>
+  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!sanitize_shallow (c))) return_trace (false);
+    unsigned int count = get_length ();
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!(*this)[i].sanitize (c, base, user_data)))
+        return_trace (false);
+    return_trace (true);
+  }
+
+  template <typename T>
+  const Type *bsearch (const T &key) const
+  {
+    unsigned int size = header.unitSize;
+    int min = 0, max = (int) get_length () - 1;
+    while (min <= max)
+    {
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
+      int c = p->cmp (key);
+      if (c < 0) max = mid - 1;
+      else if (c > 0) min = mid + 1;
+      else return p;
+    }
+    return nullptr;
+  }
+
+  private:
+  bool sanitize_shallow (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (header.sanitize (c) &&
+                  Type::static_size <= header.unitSize &&
+                  c->check_range (bytesZ.arrayZ,
+                                  header.nUnits,
+                                  header.unitSize));
+  }
+
+  protected:
+  VarSizedBinSearchHeader       header;
+  UnsizedArrayOf<HBUINT8>       bytesZ;
+  public:
+  DEFINE_SIZE_ARRAY (10, bytesZ);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OPEN_TYPE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff-common.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,713 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+#ifndef HB_OT_CFF_COMMON_HH
+#define HB_OT_CFF_COMMON_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-cff-interp-dict-common.hh"
+#include "hb-subset-plan.hh"
+
+namespace CFF {
+
+using namespace OT;
+
+#define CFF_UNDEF_CODE  0xFFFFFFFF
+
+/* utility macro */
+template<typename Type>
+static inline const Type& StructAtOffsetOrNull(const void *P, unsigned int offset)
+{ return offset? (* reinterpret_cast<const Type*> ((const char *) P + offset)): Null(Type); }
+
+inline unsigned int calcOffSize(unsigned int dataSize)
+{
+  unsigned int size = 1;
+  unsigned int offset = dataSize + 1;
+  while ((offset & ~0xFF) != 0)
+  {
+    size++;
+    offset >>= 8;
+  }
+  /* format does not support size > 4; caller should handle it as an error */
+  return size;
+}
+
+struct code_pair_t
+{
+  hb_codepoint_t  code;
+  hb_codepoint_t  glyph;
+};
+
+typedef hb_vector_t<unsigned char> str_buff_t;
+struct str_buff_vec_t : hb_vector_t<str_buff_t>
+{
+  void fini () { SUPER::fini_deep (); }
+
+  unsigned int total_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < length; i++)
+      size += (*this)[i].length;
+    return size;
+  }
+
+  private:
+  typedef hb_vector_t<str_buff_t> SUPER;
+};
+
+/* CFF INDEX */
+template <typename COUNT>
+struct CFFIndex
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
+                          (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
+                           c->check_array (offsets, offSize, count + 1) &&
+                           c->check_array ((const HBUINT8*)data_base (), 1, max_offset () - 1))));
+  }
+
+  static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
+  { return offSize * (count + 1); }
+
+  unsigned int offset_array_size () const
+  { return calculate_offset_array_size (offSize, count); }
+
+  static unsigned int calculate_serialized_size (unsigned int offSize, unsigned int count, unsigned int dataSize)
+  {
+    if (count == 0)
+      return COUNT::static_size;
+    else
+      return min_size + calculate_offset_array_size (offSize, count) + dataSize;
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size ();
+    CFFIndex *dest = c->allocate_size<CFFIndex> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const byte_str_array_t &byteArray)
+  {
+    TRACE_SERIALIZE (this);
+    if (byteArray.length == 0)
+    {
+      COUNT *dest = c->allocate_min<COUNT> ();
+      if (unlikely (dest == nullptr)) return_trace (false);
+      dest->set (0);
+    }
+    else
+    {
+      /* serialize CFFIndex header */
+      if (unlikely (!c->extend_min (*this))) return_trace (false);
+      this->count.set (byteArray.length);
+      this->offSize.set (offSize_);
+      if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
+        return_trace (false);
+
+      /* serialize indices */
+      unsigned int  offset = 1;
+      unsigned int  i = 0;
+      for (; i < byteArray.length; i++)
+      {
+        set_offset_at (i, offset);
+        offset += byteArray[i].get_size ();
+      }
+      set_offset_at (i, offset);
+
+      /* serialize data */
+      for (unsigned int i = 0; i < byteArray.length; i++)
+      {
+        const byte_str_t &bs = byteArray[i];
+        unsigned char  *dest = c->allocate_size<unsigned char> (bs.length);
+        if (unlikely (dest == nullptr))
+          return_trace (false);
+        memcpy (dest, &bs[0], bs.length);
+      }
+    }
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const str_buff_vec_t &buffArray)
+  {
+    byte_str_array_t  byteArray;
+    byteArray.init ();
+    byteArray.resize (buffArray.length);
+    for (unsigned int i = 0; i < byteArray.length; i++)
+    {
+      byteArray[i] = byte_str_t (buffArray[i].arrayZ (), buffArray[i].length);
+    }
+    bool result = this->serialize (c, offSize_, byteArray);
+    byteArray.fini ();
+    return result;
+  }
+
+  void set_offset_at (unsigned int index, unsigned int offset)
+  {
+    HBUINT8 *p = offsets + offSize * index + offSize;
+    unsigned int size = offSize;
+    for (; size; size--)
+    {
+      --p;
+      p->set (offset & 0xFF);
+      offset >>= 8;
+    }
+  }
+
+  unsigned int offset_at (unsigned int index) const
+  {
+    assert (index <= count);
+    const HBUINT8 *p = offsets + offSize * index;
+    unsigned int size = offSize;
+    unsigned int offset = 0;
+    for (; size; size--)
+      offset = (offset << 8) + *p++;
+    return offset;
+  }
+
+  unsigned int length_at (unsigned int index) const
+  {
+        if (likely ((offset_at (index + 1) >= offset_at (index)) &&
+                    (offset_at (index + 1) <= offset_at (count))))
+          return offset_at (index + 1) - offset_at (index);
+        else
+          return 0;
+  }
+
+  const unsigned char *data_base () const
+  { return (const unsigned char *)this + min_size + offset_array_size (); }
+
+  unsigned int data_size () const { return HBINT8::static_size; }
+
+  byte_str_t operator [] (unsigned int index) const
+  {
+    if (likely (index < count))
+      return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
+    else
+      return Null(byte_str_t);
+  }
+
+  unsigned int get_size () const
+  {
+    if (this != &Null(CFFIndex))
+    {
+      if (count > 0)
+        return min_size + offset_array_size () + (offset_at (count) - 1);
+      else
+        return count.static_size;  /* empty CFFIndex contains count only */
+    }
+    else
+      return 0;
+  }
+
+  protected:
+  unsigned int max_offset () const
+  {
+    unsigned int max = 0;
+    for (unsigned int i = 0; i < count + 1u; i++)
+    {
+      unsigned int off = offset_at (i);
+      if (off > max) max = off;
+    }
+    return max;
+  }
+
+  public:
+  COUNT     count;      /* Number of object data. Note there are (count+1) offsets */
+  HBUINT8   offSize;      /* The byte size of each offset in the offsets array. */
+  HBUINT8   offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
+  /* HBUINT8 data[VAR];      Object data */
+  public:
+  DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
+};
+
+template <typename COUNT, typename TYPE>
+struct CFFIndexOf : CFFIndex<COUNT>
+{
+  const byte_str_t operator [] (unsigned int index) const
+  {
+    if (likely (index < CFFIndex<COUNT>::count))
+      return byte_str_t (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
+    return Null(byte_str_t);
+  }
+
+  template <typename DATA, typename PARAM1, typename PARAM2>
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const DATA *dataArray,
+                  unsigned int dataArrayLen,
+                  const hb_vector_t<unsigned int> &dataSizeArray,
+                  const PARAM1 &param1,
+                  const PARAM2 &param2)
+  {
+    TRACE_SERIALIZE (this);
+    /* serialize CFFIndex header */
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (dataArrayLen);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
+      return_trace (false);
+
+    /* serialize indices */
+    unsigned int  offset = 1;
+    unsigned int  i = 0;
+    for (; i < dataArrayLen; i++)
+    {
+      CFFIndex<COUNT>::set_offset_at (i, offset);
+      offset += dataSizeArray[i];
+    }
+    CFFIndex<COUNT>::set_offset_at (i, offset);
+
+    /* serialize data */
+    for (unsigned int i = 0; i < dataArrayLen; i++)
+    {
+      TYPE  *dest = c->start_embed<TYPE> ();
+      if (unlikely (dest == nullptr ||
+                    !dest->serialize (c, dataArray[i], param1, param2)))
+        return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename DATA, typename PARAM>
+  static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
+                                                 const DATA *dataArray,
+                                                 unsigned int dataArrayLen,
+                                                 hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
+                                                 const PARAM &param)
+  {
+    /* determine offset size */
+    unsigned int  totalDataSize = 0;
+    for (unsigned int i = 0; i < dataArrayLen; i++)
+    {
+      unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
+      dataSizeArray[i] = dataSize;
+      totalDataSize += dataSize;
+    }
+    offSize_ = calcOffSize (totalDataSize);
+
+    return CFFIndex<COUNT>::calculate_serialized_size (offSize_, dataArrayLen, totalDataSize);
+  }
+};
+
+/* Top Dict, Font Dict, Private Dict */
+struct Dict : UnsizedByteStr
+{
+  template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
+  bool serialize (hb_serialize_context_t *c,
+                  const DICTVAL &dictval,
+                  OP_SERIALIZER& opszr,
+                  PARAM& param)
+  {
+    TRACE_SERIALIZE (this);
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+    {
+      if (unlikely (!opszr.serialize (c, dictval[i], param)))
+        return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
+  static unsigned int calculate_serialized_size (const DICTVAL &dictval,
+                                                 OP_SERIALIZER& opszr,
+                                                 PARAM& param)
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+      size += opszr.calculate_serialized_size (dictval[i], param);
+    return size;
+  }
+
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  static unsigned int calculate_serialized_size (const DICTVAL &dictval,
+                                                 OP_SERIALIZER& opszr)
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dictval.get_count (); i++)
+      size += opszr.calculate_serialized_size (dictval[i]);
+    return size;
+  }
+
+  template <typename INTTYPE, int minVal, int maxVal>
+  static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, int value, op_code_t intOp)
+  {
+    // XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
+    if (/*unlikely*/ (!serialize_int<INTTYPE, minVal, maxVal> (c, intOp, value)))
+      return false;
+
+    TRACE_SERIALIZE (this);
+    /* serialize the opcode */
+    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
+    if (unlikely (p == nullptr)) return_trace (false);
+    if (Is_OpCode_ESC (op))
+    {
+      p->set (OpCode_escape);
+      op = Unmake_OpCode_ESC (op);
+      p++;
+    }
+    p->set (op);
+    return_trace (true);
+  }
+
+  static bool serialize_uint4_op (hb_serialize_context_t *c, op_code_t op, int value)
+  { return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
+
+  static bool serialize_uint2_op (hb_serialize_context_t *c, op_code_t op, int value)
+  { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
+
+  static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
+  {
+    return serialize_uint4_op (c, op, value);
+  }
+
+  static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
+  {
+    return serialize_uint2_op (c, op, value);
+  }
+};
+
+struct TopDict : Dict {};
+struct FontDict : Dict {};
+struct PrivateDict : Dict {};
+
+struct table_info_t
+{
+  void init () { offSize = offset = size = 0; }
+
+  unsigned int    offset;
+  unsigned int    size;
+  unsigned int    offSize;
+};
+
+/* used to remap font index or SID from fullset to subset.
+ * set to CFF_UNDEF_CODE if excluded from subset */
+struct remap_t : hb_vector_t<hb_codepoint_t>
+{
+  void init () { SUPER::init (); }
+
+  void fini () { SUPER::fini (); }
+
+  bool reset (unsigned int size)
+  {
+    if (unlikely (!SUPER::resize (size)))
+      return false;
+    for (unsigned int i = 0; i < length; i++)
+      (*this)[i] = CFF_UNDEF_CODE;
+    count = 0;
+    return true;
+  }
+
+  bool identity (unsigned int size)
+  {
+    if (unlikely (!SUPER::resize (size)))
+      return false;
+    unsigned int i;
+    for (i = 0; i < length; i++)
+      (*this)[i] = i;
+    count = i;
+    return true;
+  }
+
+  bool excludes (hb_codepoint_t id) const
+  { return (id < length) && ((*this)[id] == CFF_UNDEF_CODE); }
+
+  bool includes (hb_codepoint_t id) const
+  { return !excludes (id); }
+
+  unsigned int add (unsigned int i)
+  {
+    if ((*this)[i] == CFF_UNDEF_CODE)
+      (*this)[i] = count++;
+    return (*this)[i];
+  }
+
+  hb_codepoint_t get_count () const { return count; }
+
+  protected:
+  hb_codepoint_t  count;
+
+  private:
+  typedef hb_vector_t<hb_codepoint_t> SUPER;
+};
+
+template <typename COUNT>
+struct FDArray : CFFIndexOf<COUNT, FontDict>
+{
+  /* used by CFF1 */
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const hb_vector_t<DICTVAL> &fontDicts,
+                  OP_SERIALIZER& opszr)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (fontDicts.length);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
+      return_trace (false);
+
+    /* serialize font dict offsets */
+    unsigned int  offset = 1;
+    unsigned int fid = 0;
+    for (; fid < fontDicts.length; fid++)
+    {
+      CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+      offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
+    }
+    CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+
+    /* serialize font dicts */
+    for (unsigned int i = 0; i < fontDicts.length; i++)
+    {
+      FontDict *dict = c->start_embed<FontDict> ();
+      if (unlikely (!dict->serialize (c, fontDicts[i], opszr, fontDicts[i])))
+        return_trace (false);
+    }
+    return_trace (true);
+  }
+
+  /* used by CFF2 */
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int offSize_,
+                  const hb_vector_t<DICTVAL> &fontDicts,
+                  unsigned int fdCount,
+                  const remap_t &fdmap,
+                  OP_SERIALIZER& opszr,
+                  const hb_vector_t<table_info_t> &privateInfos)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    this->count.set (fdCount);
+    this->offSize.set (offSize_);
+    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
+      return_trace (false);
+
+    /* serialize font dict offsets */
+    unsigned int  offset = 1;
+    unsigned int  fid = 0;
+    for (unsigned i = 0; i < fontDicts.length; i++)
+      if (fdmap.includes (i))
+      {
+        CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
+        offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
+      }
+    CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
+
+    /* serialize font dicts */
+    for (unsigned int i = 0; i < fontDicts.length; i++)
+      if (fdmap.includes (i))
+      {
+        FontDict *dict = c->start_embed<FontDict> ();
+        if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]])))
+          return_trace (false);
+      }
+    return_trace (true);
+  }
+
+  /* in parallel to above */
+  template <typename OP_SERIALIZER, typename DICTVAL>
+  static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
+                                                 const hb_vector_t<DICTVAL> &fontDicts,
+                                                 unsigned int fdCount,
+                                                 const remap_t &fdmap,
+                                                 OP_SERIALIZER& opszr)
+  {
+    unsigned int dictsSize = 0;
+    for (unsigned int i = 0; i < fontDicts.len; i++)
+      if (fdmap.includes (i))
+        dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
+
+    offSize_ = calcOffSize (dictsSize);
+    return CFFIndex<COUNT>::calculate_serialized_size (offSize_, fdCount, dictsSize);
+  }
+};
+
+/* FDSelect */
+struct FDSelect0 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this))))
+      return_trace (false);
+    for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
+      if (unlikely (!fds[i].sanitize (c)))
+        return_trace (false);
+
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    return (hb_codepoint_t)fds[glyph];
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  { return HBUINT8::static_size * num_glyphs; }
+
+  HBUINT8     fds[VAR];
+
+  DEFINE_SIZE_MIN (1);
+};
+
+template <typename GID_TYPE, typename FD_TYPE>
+struct FDSelect3_4_Range {
+  bool sanitize (hb_sanitize_context_t *c, const void */*nullptr*/, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (first < c->get_num_glyphs () && (fd < fdcount));
+  }
+
+  GID_TYPE    first;
+  FD_TYPE     fd;
+
+  DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
+};
+
+template <typename GID_TYPE, typename FD_TYPE>
+struct FDSelect3_4 {
+  unsigned int get_size () const
+  { return GID_TYPE::static_size * 2 + ranges.get_size (); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
+                  (nRanges () == 0) || ranges[0].first != 0))
+      return_trace (false);
+
+    for (unsigned int i = 1; i < nRanges (); i++)
+    {
+      if (unlikely (ranges[i - 1].first >= ranges[i].first))
+          return_trace (false);
+    }
+
+    if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
+      return_trace (false);
+
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    unsigned int i;
+    for (i = 1; i < nRanges (); i++)
+      if (glyph < ranges[i].first)
+        break;
+
+    return (hb_codepoint_t)ranges[i - 1].fd;
+  }
+
+  GID_TYPE &nRanges () { return ranges.len; }
+  GID_TYPE nRanges () const { return ranges.len; }
+  GID_TYPE &sentinel ()  { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
+  const GID_TYPE &sentinel () const  { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
+
+  ArrayOf<FDSelect3_4_Range<GID_TYPE, FD_TYPE>, GID_TYPE> ranges;
+  /* GID_TYPE sentinel */
+
+  DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges);
+};
+
+typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
+typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
+
+struct FDSelect {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
+                          (format == 0)?
+                          u.format0.sanitize (c, fdcount):
+                          u.format3.sanitize (c, fdcount)));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    FDSelect *dest = c->allocate_size<FDSelect> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (unsigned int num_glyphs) const
+  { return get_size (num_glyphs); }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = format.static_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else
+      size += u.format3.get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    if (this == &Null(FDSelect))
+      return 0;
+    if (format == 0)
+      return u.format0.get_fd (glyph);
+    else
+      return u.format3.get_fd (glyph);
+  }
+
+  HBUINT8       format;
+  union {
+    FDSelect0   format0;
+    FDSelect3   format3;
+  } u;
+
+  DEFINE_SIZE_MIN (1);
+};
+
+template <typename COUNT>
+struct Subrs : CFFIndex<COUNT>
+{
+  typedef COUNT count_type;
+  typedef CFFIndex<COUNT> SUPER;
+};
+
+} /* namespace CFF */
+
+#endif /* HB_OT_CFF_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff1-table.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,385 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-ot-cff1-table.hh"
+#include "hb-cff1-interp-cs.hh"
+
+using namespace CFF;
+
+/* SID to code */
+static const uint8_t standard_encoding_to_code [] =
+{
+    0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46,
+   47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62,
+   63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78,
+   79,   80,   81,   82,   83,   84,   85,   86,  87,   88,   89,   90,   91,   92,   93,   94,
+   95,   96,   97,   98,   99,  100,  101,  102, 103,  104,  105,  106,  107,  108,  109,  110,
+  111,  112,  113,  114,  115,  116,  117,  118, 119,  120,  121,  122,  123,  124,  125,  126,
+  161,  162,  163,  164,  165,  166,  167,  168, 169,  170,  171,  172,  173,  174,  175,  177,
+  178,  179,  180,  182,  183,  184,  185,  186, 187,  188,  189,  191,  193,  194,  195,  196,
+  197,  198,  199,  200,  202,  203,  205,  206, 207,  208,  225,  227,  232,  233,  234,  235,
+  241,  245,  248,  249,  250,  251
+};
+
+/* SID to code */
+static const uint8_t expert_encoding_to_code [] =
+{
+    0,   32,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   44,   45,   46,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   58,   59,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,   47,    0,    0,    0,    0,    0,    0,    0,    0,    0,   87,   88,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  201,    0,    0,    0,    0,  189,    0,    0,  188,    0,
+    0,    0,    0,  190,  202,    0,    0,    0,    0,  203,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,   33,   34,   36,   37,   38,   39,   40,   41,   42,   43,   48,
+   49,   50,   51,   52,   53,   54,   55,   56,   57,   60,   61,   62,   63,   65,   66,   67,
+   68,   69,   73,   76,   77,   78,   79,   82,   83,   84,   86,   89,   90,   91,   93,   94,
+   95,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
+  111,  112,  113,  114,  115,  116,  117,  118,  119,  120,  121,  122,  123,  124,  125,  126,
+  161,  162,  163,  166,  167,  168,  169,  170,  172,  175,  178,  179,  182,  183,  184,  191,
+  192,  193,  194,  195,  196,  197,  200,  204,  205,  206,  207,  208,  209,  210,  211,  212,
+  213,  214,  215,  216,  217,  218,  219,  220,  221,  222,  223,  224,  225,  226,  227,  228,
+  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,  239,  240,  241,  242,  243,  244,
+  245,  246,  247,  248,  249,  250,  251,  252,  253,  254,  255
+};
+
+/* glyph ID to SID */
+static const uint16_t expert_charset_to_sid [] =
+{
+    0,    1,  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,   13,   14,   15,   99,
+  239,  240,  241,  242,  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  252,
+  253,  254,  255,  256,  257,  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,
+  267,  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,  278,  279,  280,  281,  282,
+  283,  284,  285,  286,  287,  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,  298,
+  299,  300,  301,  302,  303,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  314,
+  315,  316,  317,  318,  158,  155,  163,  319,  320,  321,  322,  323,  324,  325,  326,  150,
+  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,  340,
+  341,  342,  343,  344,  345,  346,  347,  348,  349,  350,  351,  352,  353,  354,  355,  356,
+  357,  358,  359,  360,  361,  362,  363,  364,  365,  366,  367,  368,  369,  370,  371,  372,
+  373,  374,  375,  376,  377,  378
+};
+
+/* glyph ID to SID */
+static const uint16_t expert_subset_charset_to_sid [] =
+{
+    0,    1,  231,  232,  235,  236,  237,  238,   13,   14,   15,   99,  239,  240,  241,  242,
+  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  253,  254,  255,  256,  257,
+  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,  267,  268,  269,  270,  272,
+  300,  301,  302,  305,  314,  315,  158,  155,  163,  320,  321,  322,  323,  324,  325,  326,
+  150,  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,
+  340,  341,  342,  343,  344,  345,  346
+};
+
+/* code to SID */
+static const uint8_t standard_encoding_to_sid [] =
+{
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16,
+    17,  18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
+    33,  34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,
+    49,  50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,
+    65,  66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,
+    81,  82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,
+    0,  111,  112,  113,  114,    0,  115,  116,  117,  118,  119,  120,  121,  122,    0,  123,
+    0,  124,  125,  126,  127,  128,  129,  130,  131,    0,  132,  133,    0,  134,  135,  136,
+  137,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,   138,   0,  139,    0,    0,    0,    0,  140,  141,  142,  143,    0,    0,    0,    0,
+    0,   144,   0,    0,    0,  145,    0,    0,  146,  147,  148,  149,    0,    0,    0,    0
+};
+
+hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid)
+{
+  if (sid < ARRAY_LENGTH (standard_encoding_to_code))
+    return (hb_codepoint_t)standard_encoding_to_code[sid];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
+{
+  if (sid < ARRAY_LENGTH (expert_encoding_to_code))
+    return (hb_codepoint_t)expert_encoding_to_code[sid];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
+{
+  if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
+    return (hb_codepoint_t)expert_charset_to_sid[glyph];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
+{
+  if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
+    return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
+  else
+    return 0;
+}
+
+hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
+{
+  if (code < ARRAY_LENGTH (standard_encoding_to_sid))
+    return (hb_codepoint_t)standard_encoding_to_sid[code];
+  else
+    return CFF_UNDEF_SID;
+}
+
+struct bounds_t
+{
+  void init ()
+  {
+    min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
+    max.set_int (-0x80000000, -0x80000000);
+  }
+
+  void update (const point_t &pt)
+  {
+    if (pt.x < min.x) min.x = pt.x;
+    if (pt.x > max.x) max.x = pt.x;
+    if (pt.y < min.y) min.y = pt.y;
+    if (pt.y > max.y) max.y = pt.y;
+  }
+
+  void merge (const bounds_t &b)
+  {
+    if (empty ())
+      *this = b;
+    else if (!b.empty ())
+    {
+      if (b.min.x < min.x) min.x = b.min.x;
+      if (b.max.x > max.x) max.x = b.max.x;
+      if (b.min.y < min.y) min.y = b.min.y;
+      if (b.max.y > max.y) max.y = b.max.y;
+    }
+  }
+
+  void offset (const point_t &delta)
+  {
+    if (!empty ())
+    {
+      min.move (delta);
+      max.move (delta);
+    }
+  }
+
+  bool empty () const
+  { return (min.x >= max.x) || (min.y >= max.y); }
+
+  point_t min;
+  point_t max;
+};
+
+struct extents_param_t
+{
+  void init (const OT::cff1::accelerator_t *_cff)
+  {
+    path_open = false;
+    cff = _cff;
+    bounds.init ();
+  }
+
+  void start_path ()         { path_open = true; }
+  void end_path ()           { path_open = false; }
+  bool is_path_open () const { return path_open; }
+
+  bool    path_open;
+  bounds_t  bounds;
+
+  const OT::cff1::accelerator_t *cff;
+};
+
+struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, extents_param_t>
+{
+  static void moveto (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
+  {
+    param.end_path ();
+    env.moveto (pt);
+  }
+
+  static void line (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.bounds.update (env.get_pt ());
+    }
+    env.moveto (pt1);
+    param.bounds.update (env.get_pt ());
+  }
+
+  static void curve (cff1_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.bounds.update (env.get_pt ());
+    }
+    /* include control points */
+    param.bounds.update (pt1);
+    param.bounds.update (pt2);
+    env.moveto (pt3);
+    param.bounds.update (env.get_pt ());
+  }
+};
+
+static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
+
+struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, extents_param_t, cff1_path_procs_extents_t>
+{
+  static void process_seac (cff1_cs_interp_env_t &env, extents_param_t& param)
+  {
+    unsigned int  n = env.argStack.get_count ();
+    point_t delta;
+    delta.x = env.argStack[n-4];
+    delta.y = env.argStack[n-3];
+    hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
+    hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
+
+    bounds_t  base_bounds, accent_bounds;
+    if (likely (!env.in_seac && base && accent
+               && _get_bounds (param.cff, base, base_bounds, true)
+               && _get_bounds (param.cff, accent, accent_bounds, true)))
+    {
+      param.bounds.merge (base_bounds);
+      accent_bounds.offset (delta);
+      param.bounds.merge (accent_bounds);
+    }
+    else
+      env.set_error ();
+  }
+};
+
+bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
+{
+  bounds.init ();
+  if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
+
+  unsigned int fd = cff->fdSelect->get_fd (glyph);
+  cff1_cs_interpreter_t<cff1_cs_opset_extents_t, extents_param_t> interp;
+  const byte_str_t str = (*cff->charStrings)[glyph];
+  interp.env.init (str, *cff, fd);
+  interp.env.set_in_seac (in_seac);
+  extents_param_t  param;
+  param.init (cff);
+  if (unlikely (!interp.interpret (param))) return false;
+  bounds = param.bounds;
+  return true;
+}
+
+bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+{
+  bounds_t  bounds;
+
+  if (!_get_bounds (this, glyph, bounds))
+    return false;
+
+  if (bounds.min.x >= bounds.max.x)
+  {
+    extents->width = 0;
+    extents->x_bearing = 0;
+  }
+  else
+  {
+    extents->x_bearing = (int32_t)bounds.min.x.floor ();
+    extents->width = (int32_t)bounds.max.x.ceil () - extents->x_bearing;
+  }
+  if (bounds.min.y >= bounds.max.y)
+  {
+    extents->height = 0;
+    extents->y_bearing = 0;
+  }
+  else
+  {
+    extents->y_bearing = (int32_t)bounds.max.y.ceil ();
+    extents->height = (int32_t)bounds.min.y.floor () - extents->y_bearing;
+  }
+
+  return true;
+}
+
+struct get_seac_param_t
+{
+  void init (const OT::cff1::accelerator_t *_cff)
+  {
+    cff = _cff;
+    base = 0;
+    accent = 0;
+  }
+
+  bool has_seac () const { return base && accent; }
+
+  const OT::cff1::accelerator_t *cff;
+  hb_codepoint_t  base;
+  hb_codepoint_t  accent;
+};
+
+struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
+{
+  static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
+  {
+    unsigned int  n = env.argStack.get_count ();
+    hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
+    hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
+
+    param.base = param.cff->std_code_to_glyph (base_char);
+    param.accent = param.cff->std_code_to_glyph (accent_char);
+  }
+};
+
+bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
+{
+  if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
+
+  unsigned int fd = fdSelect->get_fd (glyph);
+  cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
+  const byte_str_t str = (*charStrings)[glyph];
+  interp.env.init (str, *this, fd);
+  get_seac_param_t  param;
+  param.init (this);
+  if (unlikely (!interp.interpret (param))) return false;
+
+  if (param.has_seac ())
+  {
+    *base = param.base;
+    *accent = param.accent;
+    return true;
+  }
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff1-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,1299 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_OT_CFF1_TABLE_HH
+#define HB_OT_CFF1_TABLE_HH
+
+#include "hb-ot-head-table.hh"
+#include "hb-ot-cff-common.hh"
+#include "hb-subset-cff1.hh"
+
+namespace CFF {
+
+/*
+ * CFF -- Compact Font Format (CFF)
+ * http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
+ */
+#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
+
+#define CFF_UNDEF_SID   CFF_UNDEF_CODE
+
+enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
+enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
+
+typedef CFFIndex<HBUINT16>  CFF1Index;
+template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
+
+typedef CFFIndex<HBUINT16> CFF1Index;
+typedef CFF1Index          CFF1CharStrings;
+typedef FDArray<HBUINT16>  CFF1FDArray;
+typedef Subrs<HBUINT16>    CFF1Subrs;
+
+struct CFF1FDSelect : FDSelect {};
+
+/* Encoding */
+struct Encoding0 {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && codes[nCodes - 1].sanitize (c));
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    assert (glyph > 0);
+    glyph--;
+    if (glyph < nCodes)
+    {
+      return (hb_codepoint_t)codes[glyph];
+    }
+    else
+      return CFF_UNDEF_CODE;
+  }
+
+  unsigned int get_size () const
+  { return HBUINT8::static_size * (nCodes + 1); }
+
+  HBUINT8     nCodes;
+  HBUINT8     codes[VAR];
+
+  DEFINE_SIZE_ARRAY(1, codes);
+};
+
+struct Encoding1_Range {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8   first;
+  HBUINT8   nLeft;
+
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct Encoding1 {
+  unsigned int get_size () const
+  { return HBUINT8::static_size + Encoding1_Range::static_size * nRanges; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && ((nRanges == 0) || (ranges[nRanges - 1]).sanitize (c)));
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    assert (glyph > 0);
+    glyph--;
+    for (unsigned int i = 0; i < nRanges; i++)
+    {
+      if (glyph <= ranges[i].nLeft)
+      {
+        return (hb_codepoint_t)ranges[i].first + glyph;
+      }
+      glyph -= (ranges[i].nLeft + 1);
+    }
+    return CFF_UNDEF_CODE;
+  }
+
+  HBUINT8          nRanges;
+  Encoding1_Range   ranges[VAR];
+
+  DEFINE_SIZE_ARRAY (1, ranges);
+};
+
+struct SuppEncoding {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT8   code;
+  HBUINT16  glyph;
+
+  DEFINE_SIZE_STATIC (3);
+};
+
+struct CFF1SuppEncData {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && ((nSups == 0) || (supps[nSups - 1]).sanitize (c)));
+  }
+
+  void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
+  {
+    for (unsigned int i = 0; i < nSups; i++)
+      if (sid == supps[i].glyph)
+        codes.push (supps[i].code);
+  }
+
+  unsigned int get_size () const
+  { return HBUINT8::static_size + SuppEncoding::static_size * nSups; }
+
+  HBUINT8        nSups;
+  SuppEncoding   supps[VAR];
+
+  DEFINE_SIZE_ARRAY (1, supps);
+};
+
+struct Encoding {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    unsigned int fmt = format & 0x7F;
+    if (unlikely (fmt > 1))
+      return_trace (false);
+    if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
+      return_trace (false);
+    return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
+  }
+
+  /* serialize a fullset Encoding */
+  bool serialize (hb_serialize_context_t *c, const Encoding &src)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size ();
+    Encoding *dest = c->allocate_size<Encoding> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  /* serialize a subset Encoding */
+  bool serialize (hb_serialize_context_t *c,
+                  uint8_t format,
+                  unsigned int enc_count,
+                  const hb_vector_t<code_pair_t>& code_ranges,
+                  const hb_vector_t<code_pair_t>& supp_codes)
+  {
+    TRACE_SERIALIZE (this);
+    Encoding *dest = c->extend_min (*this);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    dest->format.set (format | ((supp_codes.length > 0)? 0x80: 0));
+    if (format == 0)
+    {
+      Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
+    if (unlikely (fmt0 == nullptr)) return_trace (false);
+      fmt0->nCodes.set (enc_count);
+      unsigned int glyph = 0;
+      for (unsigned int i = 0; i < code_ranges.length; i++)
+      {
+        hb_codepoint_t code = code_ranges[i].code;
+        for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
+          fmt0->codes[glyph++].set (code++);
+        if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
+          return_trace (false);
+      }
+    }
+    else
+    {
+      Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
+      if (unlikely (fmt1 == nullptr)) return_trace (false);
+      fmt1->nRanges.set (code_ranges.length);
+      for (unsigned int i = 0; i < code_ranges.length; i++)
+      {
+        if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
+          return_trace (false);
+        fmt1->ranges[i].first.set (code_ranges[i].code);
+        fmt1->ranges[i].nLeft.set (code_ranges[i].glyph);
+      }
+    }
+    if (supp_codes.length > 0)
+    {
+      CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
+      if (unlikely (suppData == nullptr)) return_trace (false);
+      suppData->nSups.set (supp_codes.length);
+      for (unsigned int i = 0; i < supp_codes.length; i++)
+      {
+        suppData->supps[i].code.set (supp_codes[i].code);
+        suppData->supps[i].glyph.set (supp_codes[i].glyph); /* actually SID */
+      }
+    }
+    return_trace (true);
+  }
+
+  /* parallel to above: calculate the size of a subset Encoding */
+  static unsigned int calculate_serialized_size (uint8_t format,
+                                                 unsigned int enc_count,
+                                                 unsigned int supp_count)
+  {
+    unsigned int  size = min_size;
+    if (format == 0)
+      size += Encoding0::min_size + HBUINT8::static_size * enc_count;
+    else
+      size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
+    if (supp_count > 0)
+      size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
+    return size;
+  }
+
+  unsigned int get_size () const
+  {
+    unsigned int size = min_size;
+    if (table_format () == 0)
+      size += u.format0.get_size ();
+    else
+      size += u.format1.get_size ();
+    if (has_supplement ())
+      size += suppEncData ().get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_code (hb_codepoint_t glyph) const
+  {
+    if (table_format () == 0)
+      return u.format0.get_code (glyph);
+    else
+      return u.format1.get_code (glyph);
+  }
+
+  uint8_t table_format () const { return (format & 0x7F); }
+  bool  has_supplement () const { return (format & 0x80) != 0; }
+
+  void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
+  {
+    codes.resize (0);
+    if (has_supplement ())
+      suppEncData().get_codes (sid, codes);
+  }
+
+  protected:
+  const CFF1SuppEncData &suppEncData () const
+  {
+    if ((format & 0x7F) == 0)
+      return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes-1]);
+    else
+      return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges-1]);
+  }
+
+  public:
+  HBUINT8       format;
+
+  union {
+    Encoding0   format0;
+    Encoding1   format1;
+  } u;
+  /* CFF1SuppEncData  suppEncData; */
+
+  DEFINE_SIZE_MIN (1);
+};
+
+/* Charset */
+struct Charset0 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (glyph == 0)
+      return 0;
+    else
+      return sids[glyph - 1];
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (sid == 0)
+      return 0;
+
+    for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
+    {
+      if (sids[glyph-1] == sid)
+        return glyph;
+    }
+    return 0;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    assert (num_glyphs > 0);
+    return HBUINT16::static_size * (num_glyphs - 1);
+  }
+
+  HBUINT16  sids[VAR];
+
+  DEFINE_SIZE_ARRAY(0, sids);
+};
+
+template <typename TYPE>
+struct Charset_Range {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16  first;
+  TYPE      nLeft;
+
+  DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
+};
+
+template <typename TYPE>
+struct Charset1_2 {
+  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    num_glyphs--;
+    for (unsigned int i = 0; num_glyphs > 0; i++)
+    {
+      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
+        return_trace (false);
+      num_glyphs -= (ranges[i].nLeft + 1);
+    }
+    return_trace (true);
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (glyph == 0) return 0;
+    glyph--;
+    for (unsigned int i = 0;; i++)
+    {
+      if (glyph <= ranges[i].nLeft)
+        return (hb_codepoint_t)ranges[i].first + glyph;
+      glyph -= (ranges[i].nLeft + 1);
+    }
+
+    return 0;
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (sid == 0) return 0;
+    hb_codepoint_t  glyph = 1;
+    for (unsigned int i = 0;; i++)
+    {
+      if (glyph >= num_glyphs)
+        return 0;
+      if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
+        return glyph + (sid - ranges[i].first);
+      glyph += (ranges[i].nLeft + 1);
+    }
+
+    return 0;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = HBUINT8::static_size;
+    int glyph = (int)num_glyphs;
+
+    assert (glyph > 0);
+    glyph--;
+    for (unsigned int i = 0; glyph > 0; i++)
+    {
+      glyph -= (ranges[i].nLeft + 1);
+      size += Charset_Range<TYPE>::static_size;
+    }
+
+    return size;
+  }
+
+  Charset_Range<TYPE>   ranges[VAR];
+
+  DEFINE_SIZE_ARRAY (0, ranges);
+};
+
+typedef Charset1_2<HBUINT8>     Charset1;
+typedef Charset1_2<HBUINT16>    Charset2;
+typedef Charset_Range<HBUINT8>  Charset1_Range;
+typedef Charset_Range<HBUINT16> Charset2_Range;
+
+struct Charset {
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    if (unlikely (!c->check_struct (this)))
+      return_trace (false);
+    if (format == 0)
+      return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
+    else if (format == 1)
+      return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
+    else if (likely (format == 2))
+      return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
+    else
+      return_trace (false);
+  }
+
+  /* serialize a fullset Charset */
+  bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    Charset *dest = c->allocate_size<Charset> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  /* serialize a subset Charset */
+  bool serialize (hb_serialize_context_t *c,
+                  uint8_t format,
+                  unsigned int num_glyphs,
+                  const hb_vector_t<code_pair_t>& sid_ranges)
+  {
+    TRACE_SERIALIZE (this);
+    Charset *dest = c->extend_min (*this);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    dest->format.set (format);
+    if (format == 0)
+    {
+      Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
+    if (unlikely (fmt0 == nullptr)) return_trace (false);
+      unsigned int glyph = 0;
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+        hb_codepoint_t sid = sid_ranges[i].code;
+        for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
+          fmt0->sids[glyph++].set (sid++);
+      }
+    }
+    else if (format == 1)
+    {
+      Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
+      if (unlikely (fmt1 == nullptr)) return_trace (false);
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+        if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
+          return_trace (false);
+        fmt1->ranges[i].first.set (sid_ranges[i].code);
+        fmt1->ranges[i].nLeft.set (sid_ranges[i].glyph);
+      }
+    }
+    else /* format 2 */
+    {
+      Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
+      if (unlikely (fmt2 == nullptr)) return_trace (false);
+      for (unsigned int i = 0; i < sid_ranges.length; i++)
+      {
+        if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
+          return_trace (false);
+        fmt2->ranges[i].first.set (sid_ranges[i].code);
+        fmt2->ranges[i].nLeft.set (sid_ranges[i].glyph);
+      }
+    }
+    return_trace (true);
+  }
+
+  /* parallel to above: calculate the size of a subset Charset */
+  static unsigned int calculate_serialized_size (
+                        uint8_t format,
+                        unsigned int count)
+  {
+    unsigned int  size = min_size;
+    if (format == 0)
+      size += Charset0::min_size + HBUINT16::static_size * (count - 1);
+    else if (format == 1)
+      size += Charset1::min_size + Charset1_Range::static_size * count;
+    else
+      size += Charset2::min_size + Charset2_Range::static_size * count;
+
+    return size;
+  }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = min_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else if (format == 1)
+      size += u.format1.get_size (num_glyphs);
+    else
+      size += u.format2.get_size (num_glyphs);
+    return size;
+  }
+
+  hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+  {
+    if (format == 0)
+      return u.format0.get_sid (glyph);
+    else if (format == 1)
+      return u.format1.get_sid (glyph);
+    else
+      return u.format2.get_sid (glyph);
+  }
+
+  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
+  {
+    if (format == 0)
+      return u.format0.get_glyph (sid, num_glyphs);
+    else if (format == 1)
+      return u.format1.get_glyph (sid, num_glyphs);
+    else
+      return u.format2.get_glyph (sid, num_glyphs);
+  }
+
+  HBUINT8       format;
+  union {
+    Charset0    format0;
+    Charset1    format1;
+    Charset2    format2;
+  } u;
+
+  DEFINE_SIZE_MIN (1);
+};
+
+struct CFF1StringIndex : CFF1Index
+{
+  bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
+                  unsigned int offSize_, const remap_t &sidmap)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
+    {
+      if (!unlikely (c->extend_min (this->count)))
+        return_trace (false);
+      count.set (0);
+      return_trace (true);
+    }
+
+    byte_str_array_t bytesArray;
+    bytesArray.init ();
+    if (!bytesArray.resize (sidmap.get_count ()))
+      return_trace (false);
+    for (unsigned int i = 0; i < strings.count; i++)
+    {
+      hb_codepoint_t  j = sidmap[i];
+      if (j != CFF_UNDEF_CODE)
+        bytesArray[j] = strings[i];
+    }
+
+    bool result = CFF1Index::serialize (c, offSize_, bytesArray);
+    bytesArray.fini ();
+    return_trace (result);
+  }
+
+  /* in parallel to above */
+  unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const remap_t &sidmap) const
+  {
+    offSize = 0;
+    if ((count == 0) || (sidmap.get_count () == 0))
+      return count.static_size;
+
+    unsigned int dataSize = 0;
+    for (unsigned int i = 0; i < count; i++)
+      if (sidmap[i] != CFF_UNDEF_CODE)
+        dataSize += length_at (i);
+
+    offSize = calcOffSize(dataSize);
+    return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize);
+  }
+};
+
+struct cff1_top_dict_interp_env_t : num_interp_env_t
+{
+  cff1_top_dict_interp_env_t ()
+    : num_interp_env_t(), prev_offset(0), last_offset(0) {}
+
+  unsigned int prev_offset;
+  unsigned int last_offset;
+};
+
+struct name_dict_values_t
+{
+  enum name_dict_val_index_t
+  {
+      version,
+      notice,
+      copyright,
+      fullName,
+      familyName,
+      weight,
+      postscript,
+      fontName,
+      baseFontName,
+      registry,
+      ordering,
+
+      ValCount
+  };
+
+  void init ()
+  {
+    for (unsigned int i = 0; i < ValCount; i++)
+      values[i] = CFF_UNDEF_SID;
+  }
+
+  unsigned int& operator[] (unsigned int i)
+  { assert (i < ValCount); return values[i]; }
+
+  unsigned int operator[] (unsigned int i) const
+  { assert (i < ValCount); return values[i]; }
+
+  static enum name_dict_val_index_t name_op_to_index (op_code_t op)
+  {
+    switch (op) {
+      default: // can't happen - just make some compiler happy
+      case OpCode_version:
+        return version;
+      case OpCode_Notice:
+        return notice;
+      case OpCode_Copyright:
+        return copyright;
+      case OpCode_FullName:
+        return fullName;
+      case OpCode_FamilyName:
+        return familyName;
+      case OpCode_Weight:
+        return weight;
+      case OpCode_PostScript:
+        return postscript;
+      case OpCode_FontName:
+        return fontName;
+      case OpCode_BaseFontName:
+        return baseFontName;
+    }
+  }
+
+  unsigned int  values[ValCount];
+};
+
+struct cff1_top_dict_val_t : op_str_t
+{
+  unsigned int  last_arg_offset;
+};
+
+struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
+{
+  void init ()
+  {
+    top_dict_values_t<cff1_top_dict_val_t>::init ();
+
+    nameSIDs.init ();
+    ros_supplement = 0;
+    cidCount = 8720;
+    EncodingOffset = 0;
+    CharsetOffset = 0;
+    FDSelectOffset = 0;
+    privateDictInfo.init ();
+  }
+  void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
+
+  bool is_CID () const
+  { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
+
+  name_dict_values_t  nameSIDs;
+  unsigned int    ros_supplement_offset;
+  unsigned int    ros_supplement;
+  unsigned int    cidCount;
+
+  unsigned int    EncodingOffset;
+  unsigned int    CharsetOffset;
+  unsigned int    FDSelectOffset;
+  table_info_t       privateDictInfo;
+};
+
+struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
+{
+  static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
+  {
+    cff1_top_dict_val_t  val;
+    val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
+
+    switch (op) {
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+        dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_isFixedPitch:
+      case OpCode_ItalicAngle:
+      case OpCode_UnderlinePosition:
+      case OpCode_UnderlineThickness:
+      case OpCode_PaintType:
+      case OpCode_CharstringType:
+      case OpCode_UniqueID:
+      case OpCode_StrokeWidth:
+      case OpCode_SyntheticBase:
+      case OpCode_CIDFontVersion:
+      case OpCode_CIDFontRevision:
+      case OpCode_CIDFontType:
+      case OpCode_UIDBase:
+      case OpCode_FontBBox:
+      case OpCode_XUID:
+      case OpCode_BaseFontBlend:
+        env.clear_args ();
+        break;
+
+      case OpCode_CIDCount:
+        dictval.cidCount = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      case OpCode_ROS:
+        dictval.ros_supplement = env.argStack.pop_uint ();
+        dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
+        dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      case OpCode_Encoding:
+        dictval.EncodingOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        if (unlikely (dictval.EncodingOffset == 0)) return;
+        break;
+
+      case OpCode_charset:
+        dictval.CharsetOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        if (unlikely (dictval.CharsetOffset == 0)) return;
+        break;
+
+      case OpCode_FDSelect:
+        dictval.FDSelectOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      case OpCode_Private:
+        dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+        dictval.privateDictInfo.size = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        env.last_offset = env.str_ref.offset;
+        top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
+        /* Record this operand below if stack is empty, otherwise done */
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff1_font_dict_values_t : dict_values_t<op_str_t>
+{
+  void init ()
+  {
+    dict_values_t<op_str_t>::init ();
+    privateDictInfo.init ();
+    fontName = CFF_UNDEF_SID;
+  }
+  void fini () { dict_values_t<op_str_t>::fini (); }
+
+  table_info_t       privateDictInfo;
+  unsigned int    fontName;
+};
+
+struct cff1_font_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_FontName:
+        dictval.fontName = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_FontMatrix:
+      case OpCode_PaintType:
+        env.clear_args ();
+        break;
+      case OpCode_Private:
+        dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+        dictval.privateDictInfo.size = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        dict_opset_t::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+};
+
+template <typename VAL>
+struct cff1_private_dict_values_base_t : dict_values_t<VAL>
+{
+  void init ()
+  {
+    dict_values_t<VAL>::init ();
+    subrsOffset = 0;
+    localSubrs = &Null(CFF1Subrs);
+  }
+  void fini () { dict_values_t<VAL>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
+      if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
+        size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
+      else
+        size += dict_values_t<VAL>::get_value (i).str.length;
+    return size;
+  }
+
+  unsigned int      subrsOffset;
+  const CFF1Subrs    *localSubrs;
+};
+
+typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
+typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
+
+struct cff1_private_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
+  {
+    num_dict_val_t val;
+    val.init ();
+
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+        env.clear_args ();
+        break;
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+      case OpCode_initialRandomSeed:
+      case OpCode_defaultWidthX:
+      case OpCode_nominalWidthX:
+        val.single_val = env.argStack.pop_num ();
+        env.clear_args ();
+        break;
+      case OpCode_Subrs:
+        dictval.subrsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        dict_opset_t::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff1_private_dict_opset_subset : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
+  {
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ForceBold:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+      case OpCode_initialRandomSeed:
+      case OpCode_defaultWidthX:
+      case OpCode_nominalWidthX:
+        env.clear_args ();
+        break;
+
+      case OpCode_Subrs:
+        dictval.subrsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        dict_opset_t::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+};
+
+typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t;
+typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
+
+typedef CFF1Index CFF1NameIndex;
+typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
+
+} /* namespace CFF */
+
+namespace OT {
+
+using namespace CFF;
+
+struct cff1
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  likely (version.major == 1));
+  }
+
+  template <typename PRIVOPSET, typename PRIVDICTVAL>
+  struct accelerator_templ_t
+  {
+    void init (hb_face_t *face)
+    {
+      topDict.init ();
+      fontDicts.init ();
+      privateDicts.init ();
+
+      this->blob = sc.reference_table<cff1> (face);
+
+      /* setup for run-time santization */
+      sc.init (this->blob);
+      sc.start_processing ();
+
+      const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
+
+      if (cff == &Null(OT::cff1))
+      { fini (); return; }
+
+      nameIndex = &cff->nameIndex (cff);
+      if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
+      { fini (); return; }
+
+      topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
+      if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
+      { fini (); return; }
+
+      { /* parse top dict */
+        const byte_str_t topDictStr = (*topDictIndex)[0];
+        if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+        cff1_top_dict_interpreter_t top_interp;
+        top_interp.env.init (topDictStr);
+        topDict.init ();
+        if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+      }
+
+      if (is_predef_charset ())
+        charset = &Null(Charset);
+      else
+      {
+        charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
+        if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
+      }
+
+      fdCount = 1;
+      if (is_CID ())
+      {
+        fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
+        fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
+        if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
+            (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
+        { fini (); return; }
+
+        fdCount = fdArray->count;
+      }
+      else
+      {
+        fdArray = &Null(CFF1FDArray);
+        fdSelect = &Null(CFF1FDSelect);
+      }
+
+      stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
+      if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
+      { fini (); return; }
+
+      globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
+      if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
+      { fini (); return; }
+
+      charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
+
+      if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
+      { fini (); return; }
+
+      num_glyphs = charStrings->count;
+      if (num_glyphs != sc.get_num_glyphs ())
+      { fini (); return; }
+
+      privateDicts.resize (fdCount);
+      for (unsigned int i = 0; i < fdCount; i++)
+        privateDicts[i].init ();
+
+      // parse CID font dicts and gather private dicts
+      if (is_CID ())
+      {
+        for (unsigned int i = 0; i < fdCount; i++)
+        {
+          byte_str_t fontDictStr = (*fdArray)[i];
+          if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+          cff1_font_dict_values_t  *font;
+          cff1_font_dict_interpreter_t font_interp;
+          font_interp.env.init (fontDictStr);
+          font = fontDicts.push ();
+          if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; }
+          font->init ();
+          if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+          PRIVDICTVAL  *priv = &privateDicts[i];
+          const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+          if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+          dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
+          priv_interp.env.init (privDictStr);
+          priv->init ();
+          if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+
+          priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
+          if (priv->localSubrs != &Null(CFF1Subrs) &&
+              unlikely (!priv->localSubrs->sanitize (&sc)))
+          { fini (); return; }
+        }
+      }
+      else  /* non-CID */
+      {
+        cff1_top_dict_values_t  *font = &topDict;
+        PRIVDICTVAL  *priv = &privateDicts[0];
+
+        const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+        if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+        dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
+        priv_interp.env.init (privDictStr);
+        priv->init ();
+        if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
+
+        priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
+        if (priv->localSubrs != &Null(CFF1Subrs) &&
+            unlikely (!priv->localSubrs->sanitize (&sc)))
+        { fini (); return; }
+      }
+    }
+
+    void fini ()
+    {
+      sc.end_processing ();
+      topDict.fini ();
+      fontDicts.fini_deep ();
+      privateDicts.fini_deep ();
+      hb_blob_destroy (blob);
+      blob = nullptr;
+    }
+
+    bool is_valid () const { return blob != nullptr; }
+    bool is_CID () const { return topDict.is_CID (); }
+
+    bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
+
+    unsigned int std_code_to_glyph (hb_codepoint_t code) const
+    {
+      hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
+      if (unlikely (sid == CFF_UNDEF_SID))
+        return 0;
+
+      if (charset != &Null(Charset))
+        return charset->get_glyph (sid, num_glyphs);
+      else if ((topDict.CharsetOffset == ISOAdobeCharset)
+              && (code <= 228 /*zcaron*/)) return sid;
+      return 0;
+    }
+
+    protected:
+    hb_blob_t          *blob;
+    hb_sanitize_context_t   sc;
+
+    public:
+    const Charset          *charset;
+    const CFF1NameIndex     *nameIndex;
+    const CFF1TopDictIndex  *topDictIndex;
+    const CFF1StringIndex   *stringIndex;
+    const CFF1Subrs      *globalSubrs;
+    const CFF1CharStrings   *charStrings;
+    const CFF1FDArray       *fdArray;
+    const CFF1FDSelect      *fdSelect;
+    unsigned int            fdCount;
+
+    cff1_top_dict_values_t       topDict;
+    hb_vector_t<cff1_font_dict_values_t>   fontDicts;
+    hb_vector_t<PRIVDICTVAL>      privateDicts;
+
+    unsigned int            num_glyphs;
+  };
+
+  struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
+  {
+    HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
+    HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
+  };
+
+  struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
+  {
+    void init (hb_face_t *face)
+    {
+      SUPER::init (face);
+      if (blob == nullptr) return;
+
+      const OT::cff1 *cff = this->blob->as<OT::cff1> ();
+      encoding = &Null(Encoding);
+      if (is_CID ())
+      {
+        if (unlikely (charset == &Null(Charset))) { fini (); return; }
+      }
+      else
+      {
+        if (!is_predef_encoding ())
+        {
+          encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
+          if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
+        }
+      }
+    }
+
+    bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
+
+    hb_codepoint_t  glyph_to_code (hb_codepoint_t glyph) const
+    {
+      if (encoding != &Null(Encoding))
+        return encoding->get_code (glyph);
+      else
+      {
+        hb_codepoint_t  sid = glyph_to_sid (glyph);
+        if (sid == 0) return 0;
+        hb_codepoint_t  code = 0;
+        switch (topDict.EncodingOffset)
+        {
+          case  StandardEncoding:
+            code = lookup_standard_encoding_for_code (sid);
+            break;
+          case  ExpertEncoding:
+            code = lookup_expert_encoding_for_code (sid);
+            break;
+          default:
+            break;
+        }
+        return code;
+      }
+    }
+
+    hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
+    {
+      if (charset != &Null(Charset))
+        return charset->get_sid (glyph);
+      else
+      {
+        hb_codepoint_t sid = 0;
+        switch (topDict.CharsetOffset)
+        {
+          case  ISOAdobeCharset:
+            if (glyph <= 228 /*zcaron*/) sid = glyph;
+            break;
+          case  ExpertCharset:
+            sid = lookup_expert_charset_for_sid (glyph);
+            break;
+          case  ExpertSubsetCharset:
+              sid = lookup_expert_subset_charset_for_sid (glyph);
+            break;
+          default:
+            break;
+        }
+        return sid;
+      }
+    }
+
+    const Encoding        *encoding;
+
+    private:
+    typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER;
+  };
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *cff_prime = nullptr;
+
+    bool success = true;
+    if (hb_subset_cff1 (plan, &cff_prime)) {
+      success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
+      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
+      success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
+      hb_blob_destroy (head_blob);
+    } else {
+      success = false;
+    }
+    hb_blob_destroy (cff_prime);
+
+    return success;
+  }
+
+  protected:
+  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
+  HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
+  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
+
+  public:
+  FixedVersion<HBUINT8> version;          /* Version of CFF table. set to 0x0100u */
+  OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
+  HBUINT8              offSize;   /* offset size (unused?) */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct cff1_accelerator_t : cff1::accelerator_t {};
+} /* namespace OT */
+
+#endif /* HB_OT_CFF1_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff2-table.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,136 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-ot-cff2-table.hh"
+#include "hb-cff2-interp-cs.hh"
+
+using namespace CFF;
+
+struct extents_param_t
+{
+  void init ()
+  {
+    path_open = false;
+    min_x.set_int (0x7FFFFFFF);
+    min_y.set_int (0x7FFFFFFF);
+    max_x.set_int (-0x80000000);
+    max_y.set_int (-0x80000000);
+  }
+
+  void start_path ()         { path_open = true; }
+  void end_path ()           { path_open = false; }
+  bool is_path_open () const { return path_open; }
+
+  void update_bounds (const point_t &pt)
+  {
+    if (pt.x < min_x) min_x = pt.x;
+    if (pt.x > max_x) max_x = pt.x;
+    if (pt.y < min_y) min_y = pt.y;
+    if (pt.y > max_y) max_y = pt.y;
+  }
+
+  bool  path_open;
+  number_t min_x;
+  number_t min_y;
+  number_t max_x;
+  number_t max_y;
+};
+
+struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, extents_param_t>
+{
+  static void moveto (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt)
+  {
+    param.end_path ();
+    env.moveto (pt);
+  }
+
+  static void line (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.update_bounds (env.get_pt ());
+    }
+    env.moveto (pt1);
+    param.update_bounds (env.get_pt ());
+  }
+
+  static void curve (cff2_cs_interp_env_t &env, extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+  {
+    if (!param.is_path_open ())
+    {
+      param.start_path ();
+      param.update_bounds (env.get_pt ());
+    }
+    /* include control points */
+    param.update_bounds (pt1);
+    param.update_bounds (pt2);
+    env.moveto (pt3);
+    param.update_bounds (env.get_pt ());
+  }
+};
+
+struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, extents_param_t, cff2_path_procs_extents_t> {};
+
+bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
+                                           hb_codepoint_t glyph,
+                                           hb_glyph_extents_t *extents) const
+{
+  if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
+
+  unsigned int num_coords;
+  const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
+  unsigned int fd = fdSelect->get_fd (glyph);
+  cff2_cs_interpreter_t<cff2_cs_opset_extents_t, extents_param_t> interp;
+  const byte_str_t str = (*charStrings)[glyph];
+  interp.env.init (str, *this, fd, coords, num_coords);
+  extents_param_t  param;
+  param.init ();
+  if (unlikely (!interp.interpret (param))) return false;
+
+  if (param.min_x >= param.max_x)
+  {
+    extents->width = 0;
+    extents->x_bearing = 0;
+  }
+  else
+  {
+    extents->x_bearing = (int32_t)param.min_x.floor ();
+    extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing;
+  }
+  if (param.min_y >= param.max_y)
+  {
+    extents->height = 0;
+    extents->y_bearing = 0;
+  }
+  else
+  {
+    extents->y_bearing = (int32_t)param.max_y.ceil ();
+    extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
+  }
+
+  return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cff2-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,566 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_OT_CFF2_TABLE_HH
+#define HB_OT_CFF2_TABLE_HH
+
+#include "hb-ot-head-table.hh"
+#include "hb-ot-cff-common.hh"
+#include "hb-subset-cff2.hh"
+
+namespace CFF {
+
+/*
+ * CFF2 -- Compact Font Format (CFF) Version 2
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2
+ */
+#define HB_OT_TAG_cff2 HB_TAG('C','F','F','2')
+
+typedef CFFIndex<HBUINT32>  CFF2Index;
+template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
+
+typedef CFF2Index         CFF2CharStrings;
+typedef FDArray<HBUINT32> CFF2FDArray;
+typedef Subrs<HBUINT32>   CFF2Subrs;
+
+typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
+typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
+
+struct CFF2FDSelect
+{
+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
+  {
+    TRACE_SANITIZE (this);
+
+    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) &&
+                          (format == 0)?
+                          u.format0.sanitize (c, fdcount):
+                            ((format == 3)?
+                            u.format3.sanitize (c, fdcount):
+                            u.format4.sanitize (c, fdcount))));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size = src.get_size (num_glyphs);
+    CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, &src, size);
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (unsigned int num_glyphs) const
+  { return get_size (num_glyphs); }
+
+  unsigned int get_size (unsigned int num_glyphs) const
+  {
+    unsigned int size = format.static_size;
+    if (format == 0)
+      size += u.format0.get_size (num_glyphs);
+    else if (format == 3)
+      size += u.format3.get_size ();
+    else
+      size += u.format4.get_size ();
+    return size;
+  }
+
+  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
+  {
+    if (this == &Null(CFF2FDSelect))
+      return 0;
+    if (format == 0)
+      return u.format0.get_fd (glyph);
+    else if (format == 3)
+      return u.format3.get_fd (glyph);
+    else
+      return u.format4.get_fd (glyph);
+  }
+
+  HBUINT8       format;
+  union {
+    FDSelect0   format0;
+    FDSelect3   format3;
+    FDSelect4   format4;
+  } u;
+
+  DEFINE_SIZE_MIN (2);
+};
+
+struct CFF2VariationStore
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)) && c->check_range (&varStore, size) && varStore.sanitize (c));
+  }
+
+  bool serialize (hb_serialize_context_t *c, const CFF2VariationStore *varStore)
+  {
+    TRACE_SERIALIZE (this);
+    unsigned int size_ = varStore->get_size ();
+    CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
+    if (unlikely (dest == nullptr)) return_trace (false);
+    memcpy (dest, varStore, size_);
+    return_trace (true);
+  }
+
+  unsigned int get_size () const { return HBUINT16::static_size + size; }
+
+  HBUINT16      size;
+  VariationStore  varStore;
+
+  DEFINE_SIZE_MIN (2 + VariationStore::min_size);
+};
+
+struct cff2_top_dict_values_t : top_dict_values_t<>
+{
+  void init ()
+  {
+    top_dict_values_t<>::init ();
+    vstoreOffset = 0;
+    FDSelectOffset = 0;
+  }
+  void fini () { top_dict_values_t<>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < get_count (); i++)
+    {
+      op_code_t op = get_value (i).op;
+      switch (op)
+      {
+        case OpCode_vstore:
+        case OpCode_FDSelect:
+          size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
+          break;
+        default:
+          size += top_dict_values_t<>::calculate_serialized_op_size (get_value (i));
+          break;
+      }
+    }
+    return size;
+  }
+
+  unsigned int  vstoreOffset;
+  unsigned int  FDSelectOffset;
+};
+
+struct cff2_top_dict_opset_t : top_dict_opset_t<>
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff2_top_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_FontMatrix:
+        {
+          dict_val_t val;
+          val.init ();
+          dictval.add_op (op, env.str_ref);
+          env.clear_args ();
+        }
+        break;
+
+      case OpCode_vstore:
+        dictval.vstoreOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_FDSelect:
+        dictval.FDSelectOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        SUPER::process_op (op, env, dictval);
+        /* Record this operand below if stack is empty, otherwise done */
+        if (!env.argStack.is_empty ()) return;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  typedef top_dict_opset_t<> SUPER;
+};
+
+struct cff2_font_dict_values_t : dict_values_t<op_str_t>
+{
+  void init ()
+  {
+    dict_values_t<op_str_t>::init ();
+    privateDictInfo.init ();
+  }
+  void fini () { dict_values_t<op_str_t>::fini (); }
+
+  table_info_t    privateDictInfo;
+};
+
+struct cff2_font_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, num_interp_env_t& env, cff2_font_dict_values_t& dictval)
+  {
+    switch (op) {
+      case OpCode_Private:
+        dictval.privateDictInfo.offset = env.argStack.pop_uint ();
+        dictval.privateDictInfo.size = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        SUPER::process_op (op, env);
+        if (!env.argStack.is_empty ())
+          return;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  private:
+  typedef dict_opset_t SUPER;
+};
+
+template <typename VAL>
+struct cff2_private_dict_values_base_t : dict_values_t<VAL>
+{
+  void init ()
+  {
+    dict_values_t<VAL>::init ();
+    subrsOffset = 0;
+    localSubrs = &Null(CFF2Subrs);
+    ivs = 0;
+  }
+  void fini () { dict_values_t<VAL>::fini (); }
+
+  unsigned int calculate_serialized_size () const
+  {
+    unsigned int size = 0;
+    for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
+      if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
+        size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
+      else
+        size += dict_values_t<VAL>::get_value (i).str.length;
+    return size;
+  }
+
+  unsigned int      subrsOffset;
+  const CFF2Subrs   *localSubrs;
+  unsigned int      ivs;
+};
+
+typedef cff2_private_dict_values_base_t<op_str_t> cff2_private_dict_values_subset_t;
+typedef cff2_private_dict_values_base_t<num_dict_val_t> cff2_private_dict_values_t;
+
+struct cff2_priv_dict_interp_env_t : num_interp_env_t
+{
+  void init (const byte_str_t &str)
+  {
+    num_interp_env_t::init (str);
+    ivs = 0;
+    seen_vsindex = false;
+  }
+
+  void process_vsindex ()
+  {
+    if (likely (!seen_vsindex))
+    {
+      set_ivs (argStack.pop_uint ());
+    }
+    seen_vsindex = true;
+  }
+
+  unsigned int get_ivs () const { return ivs; }
+  void   set_ivs (unsigned int ivs_) { ivs = ivs_; }
+
+  protected:
+  unsigned int  ivs;
+  bool    seen_vsindex;
+};
+
+struct cff2_private_dict_opset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_t& dictval)
+  {
+    num_dict_val_t val;
+    val.init ();
+
+    switch (op) {
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_ExpansionFactor:
+      case OpCode_LanguageGroup:
+        val.single_val = env.argStack.pop_num ();
+        env.clear_args ();
+        break;
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+        env.clear_args ();
+        break;
+      case OpCode_Subrs:
+        dictval.subrsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+      case OpCode_vsindexdict:
+        env.process_vsindex ();
+        dictval.ivs = env.get_ivs ();
+        env.clear_args ();
+        break;
+      case OpCode_blenddict:
+        break;
+
+      default:
+        dict_opset_t::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref, val);
+  }
+};
+
+struct cff2_private_dict_opset_subset_t : dict_opset_t
+{
+  static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_subset_t& dictval)
+  {
+    switch (op) {
+      case OpCode_BlueValues:
+      case OpCode_OtherBlues:
+      case OpCode_FamilyBlues:
+      case OpCode_FamilyOtherBlues:
+      case OpCode_StdHW:
+      case OpCode_StdVW:
+      case OpCode_BlueScale:
+      case OpCode_BlueShift:
+      case OpCode_BlueFuzz:
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+      case OpCode_LanguageGroup:
+      case OpCode_ExpansionFactor:
+        env.clear_args ();
+        break;
+
+      case OpCode_blenddict:
+        env.clear_args ();
+        return;
+
+      case OpCode_Subrs:
+        dictval.subrsOffset = env.argStack.pop_uint ();
+        env.clear_args ();
+        break;
+
+      default:
+        SUPER::process_op (op, env);
+        if (!env.argStack.is_empty ()) return;
+        break;
+    }
+
+    if (unlikely (env.in_error ())) return;
+
+    dictval.add_op (op, env.str_ref);
+  }
+
+  private:
+  typedef dict_opset_t SUPER;
+};
+
+typedef dict_interpreter_t<cff2_top_dict_opset_t, cff2_top_dict_values_t> cff2_top_dict_interpreter_t;
+typedef dict_interpreter_t<cff2_font_dict_opset_t, cff2_font_dict_values_t> cff2_font_dict_interpreter_t;
+
+} /* namespace CFF */
+
+namespace OT {
+
+using namespace CFF;
+
+struct cff2
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff2;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  likely (version.major == 2));
+  }
+
+  template <typename PRIVOPSET, typename PRIVDICTVAL>
+  struct accelerator_templ_t
+  {
+    void init (hb_face_t *face)
+    {
+      topDict.init ();
+      fontDicts.init ();
+      privateDicts.init ();
+
+      this->blob = sc.reference_table<cff2> (face);
+
+      /* setup for run-time santization */
+      sc.init (this->blob);
+      sc.start_processing ();
+
+      const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
+
+      if (cff2 == &Null(OT::cff2))
+      { fini (); return; }
+
+      { /* parse top dict */
+        byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
+        if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
+        cff2_top_dict_interpreter_t top_interp;
+        top_interp.env.init (topDictStr);
+        topDict.init ();
+        if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
+      }
+
+      globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize);
+      varStore = &StructAtOffsetOrNull<CFF2VariationStore> (cff2, topDict.vstoreOffset);
+      charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset);
+      fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset);
+      fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset);
+
+      if (((varStore != &Null(CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
+          (charStrings == &Null(CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
+          (globalSubrs == &Null(CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
+          (fdArray == &Null(CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
+          (((fdSelect != &Null(CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
+      { fini (); return; }
+
+      num_glyphs = charStrings->count;
+      if (num_glyphs != sc.get_num_glyphs ())
+      { fini (); return; }
+
+      fdCount = fdArray->count;
+      privateDicts.resize (fdCount);
+
+      /* parse font dicts and gather private dicts */
+      for (unsigned int i = 0; i < fdCount; i++)
+      {
+        const byte_str_t fontDictStr = (*fdArray)[i];
+        if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
+        cff2_font_dict_values_t  *font;
+        cff2_font_dict_interpreter_t font_interp;
+        font_interp.env.init (fontDictStr);
+        font = fontDicts.push ();
+        if (unlikely (font == &Crap(cff2_font_dict_values_t))) { fini (); return; }
+        font->init ();
+        if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
+
+        const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
+        if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
+        dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t>  priv_interp;
+        priv_interp.env.init(privDictStr);
+        privateDicts[i].init ();
+        if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; }
+
+        privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
+        if (privateDicts[i].localSubrs != &Null(CFF2Subrs) &&
+          unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
+        { fini (); return; }
+      }
+    }
+
+    void fini ()
+    {
+      sc.end_processing ();
+      topDict.fini ();
+      fontDicts.fini_deep ();
+      privateDicts.fini_deep ();
+      hb_blob_destroy (blob);
+      blob = nullptr;
+    }
+
+    bool is_valid () const { return blob != nullptr; }
+
+    protected:
+    hb_blob_t                   *blob;
+    hb_sanitize_context_t       sc;
+
+    public:
+    cff2_top_dict_values_t      topDict;
+    const CFF2Subrs             *globalSubrs;
+    const CFF2VariationStore    *varStore;
+    const CFF2CharStrings       *charStrings;
+    const CFF2FDArray           *fdArray;
+    const CFF2FDSelect          *fdSelect;
+    unsigned int                fdCount;
+
+    hb_vector_t<cff2_font_dict_values_t>     fontDicts;
+    hb_vector_t<PRIVDICTVAL>  privateDicts;
+
+    unsigned int              num_glyphs;
+  };
+
+  struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t>
+  {
+    HB_INTERNAL bool get_extents (hb_font_t *font,
+                                  hb_codepoint_t glyph,
+                                  hb_glyph_extents_t *extents) const;
+  };
+
+  typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *cff2_prime = nullptr;
+
+    bool success = true;
+    if (hb_subset_cff2 (plan, &cff2_prime)) {
+      success = success && plan->add_table (HB_OT_TAG_cff2, cff2_prime);
+      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
+      success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
+      hb_blob_destroy (head_blob);
+    } else {
+      success = false;
+    }
+    hb_blob_destroy (cff2_prime);
+
+    return success;
+  }
+
+  public:
+  FixedVersion<HBUINT8>         version;        /* Version of CFF2 table. set to 0x0200u */
+  NNOffsetTo<TopDict, HBUINT8>  topDict;        /* headerSize = Offset to Top DICT. */
+  HBUINT16                      topDictSize;    /* Top DICT size */
+
+  public:
+  DEFINE_SIZE_STATIC (5);
+};
+
+struct cff2_accelerator_t : cff2::accelerator_t {};
+} /* namespace OT */
+
+#endif /* HB_OT_CFF2_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cmap-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-cmap-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,9 +27,8 @@
 #ifndef HB_OT_CMAP_TABLE_HH
 #define HB_OT_CMAP_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-set-private.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
+#include "hb-set.hh"
 
 /*
  * cmap -- Character to Glyph Index Mapping
@@ -37,13 +36,12 @@
  */
 #define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
 
-
 namespace OT {
 
 
 struct CmapSubtableFormat0
 {
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
     hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
     if (!gid)
@@ -51,8 +49,14 @@
     *glyph = gid;
     return true;
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    for (unsigned int i = 0; i < 256; i++)
+      if (glyphIdArray[i])
+        out->add (i);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -88,23 +92,23 @@
     this->format.set (4);
     this->length.set (get_sub_table_size (segments));
 
-    this->segCountX2.set (segments.len * 2);
-    this->entrySelector.set (MAX (1u, _hb_bit_storage (segments.len)) - 1);
+    this->segCountX2.set (segments.length * 2);
+    this->entrySelector.set (MAX (1u, hb_bit_storage (segments.length)) - 1);
     this->searchRange.set (2 * (1u << this->entrySelector));
-    this->rangeShift.set (segments.len * 2 > this->searchRange
-                          ? 2 * segments.len - this->searchRange
+    this->rangeShift.set (segments.length * 2 > this->searchRange
+                          ? 2 * segments.length - this->searchRange
                           : 0);
 
-    HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
+    HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
     c->allocate_size<HBUINT16> (HBUINT16::static_size); // 2 bytes of padding.
-    HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
-    HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.len);
-    HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.len);
+    HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
+    HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.length);
+    HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
 
     if (id_range_offset == nullptr)
       return_trace (false);
 
-    for (unsigned int i = 0; i < segments.len; i++)
+    for (unsigned int i = 0; i < segments.length; i++)
     {
       end_count[i].set (segments[i].end_code);
       start_count[i].set (segments[i].start_code);
@@ -150,10 +154,10 @@
     return_trace (true);
   }
 
-  static inline size_t get_sub_table_size (const hb_vector_t<segment_plan> &segments)
+  static size_t get_sub_table_size (const hb_vector_t<segment_plan> &segments)
   {
     size_t segment_size = 0;
-    for (unsigned int i = 0; i < segments.len; i++)
+    for (unsigned int i = 0; i < segments.length; i++)
     {
       // Parallel array entries
       segment_size +=
@@ -172,8 +176,8 @@
         + segment_size;
   }
 
-  static inline bool create_sub_table_plan (const hb_subset_plan_t *plan,
-                                            hb_vector_t<segment_plan> *segments)
+  static bool create_sub_table_plan (const hb_subset_plan_t *plan,
+                                     hb_vector_t<segment_plan> *segments)
   {
     segment_plan *segment = nullptr;
     hb_codepoint_t last_gid = 0;
@@ -187,13 +191,11 @@
         return false;
       }
 
-      if (cp > 0xFFFF) {
-        // We are now outside of unicode BMP, stop adding to this cmap.
-        break;
-      }
+      /* Stop adding to cmap if we are now outside of unicode BMP. */
+      if (cp > 0xFFFF) break;
 
-      if (!segment
-          || cp != segment->end_code + 1u)
+      if (!segment ||
+          cp != segment->end_code + 1u)
       {
         segment = segments->push ();
         segment->start_code.set (cp);
@@ -224,29 +226,32 @@
 
   struct accelerator_t
   {
-    inline void init (const CmapSubtableFormat4 *subtable)
+    accelerator_t () {}
+    accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); }
+    ~accelerator_t () { fini (); }
+
+    void init (const CmapSubtableFormat4 *subtable)
     {
       segCount = subtable->segCountX2 / 2;
-      endCount = subtable->values;
+      endCount = subtable->values.arrayZ;
       startCount = endCount + segCount + 1;
       idDelta = startCount + segCount;
       idRangeOffset = idDelta + segCount;
       glyphIdArray = idRangeOffset + segCount;
       glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
     }
-
-    static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
-    {
-      const accelerator_t *thiz = (const accelerator_t *) obj;
+    void fini () {}
 
+    bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+    {
       /* Custom two-array bsearch. */
-      int min = 0, max = (int) thiz->segCount - 1;
-      const HBUINT16 *startCount = thiz->startCount;
-      const HBUINT16 *endCount = thiz->endCount;
+      int min = 0, max = (int) this->segCount - 1;
+      const HBUINT16 *startCount = this->startCount;
+      const HBUINT16 *endCount = this->endCount;
       unsigned int i;
       while (min <= max)
       {
-        int mid = (min + max) / 2;
+        int mid = ((unsigned int) min + (unsigned int) max) / 2;
         if (codepoint < startCount[mid])
           max = mid - 1;
         else if (codepoint > endCount[mid])
@@ -261,33 +266,55 @@
 
     found:
       hb_codepoint_t gid;
-      unsigned int rangeOffset = thiz->idRangeOffset[i];
+      unsigned int rangeOffset = this->idRangeOffset[i];
       if (rangeOffset == 0)
-        gid = codepoint + thiz->idDelta[i];
+        gid = codepoint + this->idDelta[i];
       else
       {
         /* Somebody has been smoking... */
-        unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
-        if (unlikely (index >= thiz->glyphIdArrayLength))
+        unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
+        if (unlikely (index >= this->glyphIdArrayLength))
           return false;
-        gid = thiz->glyphIdArray[index];
+        gid = this->glyphIdArray[index];
         if (unlikely (!gid))
           return false;
-        gid += thiz->idDelta[i];
+        gid += this->idDelta[i];
       }
-
-      *glyph = gid & 0xFFFFu;
+      gid &= 0xFFFFu;
+      if (!gid)
+        return false;
+      *glyph = gid;
       return true;
     }
-
-    static inline void get_all_codepoints_func (const void *obj, hb_set_t *out)
+    static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
+    {
+      return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph);
+    }
+    void collect_unicodes (hb_set_t *out) const
     {
-      const accelerator_t *thiz = (const accelerator_t *) obj;
-      for (unsigned int i = 0; i < thiz->segCount; i++)
+      unsigned int count = this->segCount;
+      if (count && this->startCount[count - 1] == 0xFFFFu)
+        count--; /* Skip sentinel segment. */
+      for (unsigned int i = 0; i < count; i++)
       {
-        if (thiz->startCount[i] != 0xFFFFu
-            || thiz->endCount[i] != 0xFFFFu) // Skip the last segment (0xFFFF)
-          hb_set_add_range (out, thiz->startCount[i], thiz->endCount[i]);
+        unsigned int rangeOffset = this->idRangeOffset[i];
+        if (rangeOffset == 0)
+          out->add_range (this->startCount[i], this->endCount[i]);
+        else
+        {
+          for (hb_codepoint_t codepoint = this->startCount[i];
+               codepoint <= this->endCount[i];
+               codepoint++)
+          {
+            unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
+            if (unlikely (index >= this->glyphIdArrayLength))
+              break;
+            hb_codepoint_t gid = this->glyphIdArray[index];
+            if (unlikely (!gid))
+              continue;
+            out->add (codepoint);
+          }
+        }
       }
     }
 
@@ -300,14 +327,18 @@
     unsigned int glyphIdArrayLength;
   };
 
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
-    accelerator_t accel;
-    accel.init (this);
+    accelerator_t accel (this);
     return accel.get_glyph_func (&accel, codepoint, glyph);
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    accelerator_t accel (this);
+    accel.collect_unicodes (out);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
@@ -340,7 +371,8 @@
   HBUINT16      entrySelector;  /* log2(searchRange/2) */
   HBUINT16      rangeShift;     /* 2 x segCount - searchRange */
 
-  HBUINT16      values[VAR];
+  UnsizedArrayOf<HBUINT16>
+                values;
 #if 0
   HBUINT16      endCount[segCount];     /* End characterCode for each segment,
                                          * last=0xFFFFu. */
@@ -348,7 +380,8 @@
   HBUINT16      startCount[segCount];   /* Start character code for each segment. */
   HBINT16               idDelta[segCount];      /* Delta for all character codes in segment. */
   HBUINT16      idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
-  HBUINT16      glyphIdArray[VAR];      /* Glyph index array (arbitrary length) */
+  UnsizedArrayOf<HBUINT16>
+                glyphIdArray;   /* Glyph index array (arbitrary length) */
 #endif
 
   public:
@@ -370,7 +403,7 @@
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -380,15 +413,16 @@
   HBUINT32              startCharCode;  /* First character code in this group. */
   HBUINT32              endCharCode;    /* Last character code in this group. */
   HBUINT32              glyphID;        /* Glyph index; interpretation depends on
-                                 * subtable format. */
+                                         * subtable format. */
   public:
   DEFINE_SIZE_STATIC (12);
 };
+DECLARE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup);
 
 template <typename UINT>
 struct CmapSubtableTrimmed
 {
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
     /* Rely on our implicit array bound-checking. */
     hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
@@ -397,8 +431,16 @@
     *glyph = gid;
     return true;
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    hb_codepoint_t start = startCharCode;
+    unsigned int count = glyphIdArray.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (glyphIdArray[i])
+        out->add (start + i);
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
@@ -424,37 +466,36 @@
 {
   friend struct cmap;
 
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
   {
-    int i = groups.bsearch (codepoint);
-    if (i == -1)
+    hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
+    if (!gid)
       return false;
-    *glyph = T::group_get_glyph (groups[i], codepoint);
+    *glyph = gid;
     return true;
   }
 
-  inline void get_all_codepoints (hb_set_t *out) const
+  void collect_unicodes (hb_set_t *out) const
   {
     for (unsigned int i = 0; i < this->groups.len; i++) {
-      hb_set_add_range (out,
-                        this->groups[i].startCharCode,
-                        this->groups[i].endCharCode);
+      out->add_range (this->groups[i].startCharCode,
+                      MIN ((hb_codepoint_t) this->groups[i].endCharCode,
+                           (hb_codepoint_t) HB_UNICODE_MAX));
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && groups.sanitize (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         const hb_vector_t<CmapSubtableLongGroup> &group_data)
+  bool serialize (hb_serialize_context_t *c,
+                  const hb_vector_t<CmapSubtableLongGroup> &group_data)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    Supplier<CmapSubtableLongGroup> supplier (group_data.arrayZ, group_data.len);
-    if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false);
+    if (unlikely (!groups.serialize (c, group_data.as_array ()))) return_trace (false);
     return true;
   }
 
@@ -471,9 +512,10 @@
 
 struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
 {
-  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
-                                                hb_codepoint_t u)
-  { return group.glyphID + (u - group.startCharCode); }
+  static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+                                         hb_codepoint_t u)
+  { return likely (group.startCharCode <= group.endCharCode) ?
+           group.glyphID + (u - group.startCharCode) : 0; }
 
 
   bool serialize (hb_serialize_context_t *c,
@@ -488,13 +530,13 @@
     return CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups);
   }
 
-  static inline size_t get_sub_table_size (const hb_vector_t<CmapSubtableLongGroup> &groups)
+  static size_t get_sub_table_size (const hb_vector_t<CmapSubtableLongGroup> &groups)
   {
-    return 16 + 12 * groups.len;
+    return 16 + 12 * groups.length;
   }
 
-  static inline bool create_sub_table_plan (const hb_subset_plan_t *plan,
-                                            hb_vector_t<CmapSubtableLongGroup> *groups)
+  static bool create_sub_table_plan (const hb_subset_plan_t *plan,
+                                     hb_vector_t<CmapSubtableLongGroup> *groups)
   {
     CmapSubtableLongGroup *group = nullptr;
 
@@ -513,14 +555,12 @@
         group->startCharCode.set (cp);
         group->endCharCode.set (cp);
         group->glyphID.set (new_gid);
-      } else
-      {
-        group->endCharCode.set (cp);
       }
+      else group->endCharCode.set (cp);
     }
 
     DEBUG_MSG(SUBSET, nullptr, "cmap");
-    for (unsigned int i = 0; i < groups->len; i++) {
+    for (unsigned int i = 0; i < groups->length; i++) {
       CmapSubtableLongGroup& group = (*groups)[i];
       DEBUG_MSG(SUBSET, nullptr, "  %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
     }
@@ -529,9 +569,9 @@
   }
 
  private:
-  static inline bool _is_gid_consecutive (CmapSubtableLongGroup *group,
-                                          hb_codepoint_t cp,
-                                          hb_codepoint_t new_gid)
+  static bool _is_gid_consecutive (CmapSubtableLongGroup *group,
+                                   hb_codepoint_t cp,
+                                   hb_codepoint_t new_gid)
   {
     return (cp - 1 == group->endCharCode) &&
         new_gid == group->glyphID + (cp - group->startCharCode);
@@ -541,8 +581,8 @@
 
 struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
 {
-  static inline hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
-                                                hb_codepoint_t u HB_UNUSED)
+  static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
+                                         hb_codepoint_t u HB_UNUSED)
   { return group.glyphID; }
 };
 
@@ -555,36 +595,52 @@
 
 struct UnicodeValueRange
 {
-  inline int cmp (const hb_codepoint_t &codepoint) const
+  int cmp (const hb_codepoint_t &codepoint) const
   {
     if (codepoint < startUnicodeValue) return -1;
     if (codepoint > startUnicodeValue + additionalCount) return +1;
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
   HBUINT24      startUnicodeValue;      /* First value in this range. */
-  HBUINT8               additionalCount;        /* Number of additional values in this
+  HBUINT8       additionalCount;        /* Number of additional values in this
                                          * range. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
-typedef SortedArrayOf<UnicodeValueRange, HBUINT32> DefaultUVS;
+struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
+{
+  void collect_unicodes (hb_set_t *out) const
+  {
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      hb_codepoint_t first = arrayZ[i].startUnicodeValue;
+      hb_codepoint_t last = MIN ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
+                                 (hb_codepoint_t) HB_UNICODE_MAX);
+      out->add_range (first, last);
+    }
+  }
+
+  public:
+  DEFINE_SIZE_ARRAY (4, *this);
+};
 
 struct UVSMapping
 {
-  inline int cmp (const hb_codepoint_t &codepoint) const
+  int cmp (const hb_codepoint_t &codepoint) const
   {
     return unicodeValue.cmp (codepoint);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -596,35 +652,48 @@
   DEFINE_SIZE_STATIC (5);
 };
 
-typedef SortedArrayOf<UVSMapping, HBUINT32> NonDefaultUVS;
+struct NonDefaultUVS : SortedArrayOf<UVSMapping, HBUINT32>
+{
+  void collect_unicodes (hb_set_t *out) const
+  {
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+      out->add (arrayZ[i].glyphID);
+  }
+
+  public:
+  DEFINE_SIZE_ARRAY (4, *this);
+};
 
 struct VariationSelectorRecord
 {
-  inline glyph_variant_t get_glyph (hb_codepoint_t codepoint,
-                                    hb_codepoint_t *glyph,
-                                    const void *base) const
+  glyph_variant_t get_glyph (hb_codepoint_t codepoint,
+                             hb_codepoint_t *glyph,
+                             const void *base) const
   {
-    int i;
-    const DefaultUVS &defaults = base+defaultUVS;
-    i = defaults.bsearch (codepoint);
-    if (i != -1)
+    if ((base+defaultUVS).bfind (codepoint))
       return GLYPH_VARIANT_USE_DEFAULT;
-    const NonDefaultUVS &nonDefaults = base+nonDefaultUVS;
-    i = nonDefaults.bsearch (codepoint);
-    if (i != -1)
+    const UVSMapping &nonDefault = (base+nonDefaultUVS).bsearch (codepoint);
+    if (nonDefault.glyphID)
     {
-      *glyph = nonDefaults[i].glyphID;
+      *glyph = nonDefault.glyphID;
        return GLYPH_VARIANT_FOUND;
     }
     return GLYPH_VARIANT_NOT_FOUND;
   }
 
-  inline int cmp (const hb_codepoint_t &variation_selector) const
+  void collect_unicodes (hb_set_t *out, const void *base) const
+  {
+    (base+defaultUVS).collect_unicodes (out);
+    (base+nonDefaultUVS).collect_unicodes (out);
+  }
+
+  int cmp (const hb_codepoint_t &variation_selector) const
   {
     return varSelector.cmp (variation_selector);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -634,23 +703,35 @@
 
   HBUINT24      varSelector;    /* Variation selector. */
   LOffsetTo<DefaultUVS>
-                defaultUVS;     /* Offset to Default UVS Table. May be 0. */
+                defaultUVS;     /* Offset to Default UVS Table.  May be 0. */
   LOffsetTo<NonDefaultUVS>
-                nonDefaultUVS;  /* Offset to Non-Default UVS Table. May be 0. */
+                nonDefaultUVS;  /* Offset to Non-Default UVS Table.  May be 0. */
   public:
   DEFINE_SIZE_STATIC (11);
 };
 
 struct CmapSubtableFormat14
 {
-  inline glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
-                                            hb_codepoint_t variation_selector,
-                                            hb_codepoint_t *glyph) const
+  glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
+                                     hb_codepoint_t variation_selector,
+                                     hb_codepoint_t *glyph) const
   {
-    return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this);
+    return record.bsearch (variation_selector).get_glyph (codepoint, glyph, this);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  void collect_variation_selectors (hb_set_t *out) const
+  {
+    unsigned int count = record.len;
+    for (unsigned int i = 0; i < count; i++)
+      out->add (record.arrayZ[i].varSelector);
+  }
+  void collect_variation_unicodes (hb_codepoint_t variation_selector,
+                                   hb_set_t *out) const
+  {
+    record.bsearch (variation_selector).collect_unicodes (out, this);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -671,8 +752,8 @@
 {
   /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
 
-  inline bool get_glyph (hb_codepoint_t codepoint,
-                         hb_codepoint_t *glyph) const
+  bool get_glyph (hb_codepoint_t codepoint,
+                  hb_codepoint_t *glyph) const
   {
     switch (u.format) {
     case  0: return u.format0 .get_glyph (codepoint, glyph);
@@ -685,8 +766,21 @@
     default: return false;
     }
   }
+  void collect_unicodes (hb_set_t *out) const
+  {
+    switch (u.format) {
+    case  0: u.format0 .collect_unicodes (out); return;
+    case  4: u.format4 .collect_unicodes (out); return;
+    case  6: u.format6 .collect_unicodes (out); return;
+    case 10: u.format10.collect_unicodes (out); return;
+    case 12: u.format12.collect_unicodes (out); return;
+    case 13: u.format13.collect_unicodes (out); return;
+    case 14:
+    default: return;
+    }
+  }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -720,7 +814,7 @@
 
 struct EncodingRecord
 {
-  inline int cmp (const EncodingRecord &other) const
+  int cmp (const EncodingRecord &other) const
   {
     int ret;
     ret = platformID.cmp (other.platformID);
@@ -730,7 +824,7 @@
     return 0;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -747,22 +841,11 @@
 
 struct cmap
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_cmap;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
 
-  struct subset_plan {
-    subset_plan(void)
-    {
-      format4_segments.init();
-      format12_groups.init();
-    }
-
-    ~subset_plan(void)
-    {
-      format4_segments.fini();
-      format12_groups.fini();
-    }
-
-    inline size_t final_size() const
+  struct subset_plan
+  {
+    size_t final_size () const
     {
       return 4 // header
           +  8 * 3 // 3 EncodingRecord
@@ -770,67 +853,57 @@
           +  CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
     }
 
-    // Format 4
     hb_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
-    // Format 12
     hb_vector_t<CmapSubtableLongGroup> format12_groups;
   };
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool _create_plan (const hb_subset_plan_t *plan,
+                     subset_plan *cmap_plan) const
   {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  likely (version == 0) &&
-                  encodingRecord.sanitize (c, this));
-  }
-
-  inline bool _create_plan (const hb_subset_plan_t *plan,
-                            subset_plan *cmap_plan) const
-  {
-    if (unlikely( !CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
+    if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
       return false;
 
     return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
   }
 
-  inline bool _subset (const hb_subset_plan_t *plan,
-                       const subset_plan &cmap_subset_plan,
-                       size_t dest_sz,
-                       void *dest) const
+  bool _subset (const hb_subset_plan_t *plan,
+                const subset_plan &cmap_subset_plan,
+                size_t dest_sz,
+                void *dest) const
   {
     hb_serialize_context_t c (dest, dest_sz);
 
-    OT::cmap *cmap = c.start_serialize<OT::cmap> ();
-    if (unlikely (!c.extend_min (*cmap)))
+    cmap *table = c.start_serialize<cmap> ();
+    if (unlikely (!c.extend_min (*table)))
     {
       return false;
     }
 
-    cmap->version.set (0);
+    table->version.set (0);
 
-    if (unlikely (!cmap->encodingRecord.serialize (&c, /* numTables */ 3)))
+    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3)))
       return false;
 
     // TODO(grieger): Convert the below to a for loop
 
     // Format 4, Plat 0 Encoding Record
-    EncodingRecord &format4_plat0_rec = cmap->encodingRecord[0];
+    EncodingRecord &format4_plat0_rec = table->encodingRecord[0];
     format4_plat0_rec.platformID.set (0); // Unicode
     format4_plat0_rec.encodingID.set (3);
 
     // Format 4, Plat 3 Encoding Record
-    EncodingRecord &format4_plat3_rec = cmap->encodingRecord[1];
+    EncodingRecord &format4_plat3_rec = table->encodingRecord[1];
     format4_plat3_rec.platformID.set (3); // Windows
     format4_plat3_rec.encodingID.set (1); // Unicode BMP
 
     // Format 12 Encoding Record
-    EncodingRecord &format12_rec = cmap->encodingRecord[2];
+    EncodingRecord &format12_rec = table->encodingRecord[2];
     format12_rec.platformID.set (3); // Windows
     format12_rec.encodingID.set (10); // Unicode UCS-4
 
     // Write out format 4 sub table
     {
-      CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, cmap);
+      CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table);
       format4_plat3_rec.subtable.set (format4_plat0_rec.subtable);
       subtable.u.format.set (4);
 
@@ -841,7 +914,7 @@
 
     // Write out format 12 sub table.
     {
-      CmapSubtable &subtable = format12_rec.subtable.serialize (&c, cmap);
+      CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
       subtable.u.format.set (12);
 
       CmapSubtableFormat12 &format12 = subtable.u.format12;
@@ -854,7 +927,7 @@
     return true;
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     subset_plan cmap_subset_plan;
 
@@ -865,7 +938,7 @@
     }
 
     // We now know how big our blob needs to be
-    size_t dest_sz = cmap_subset_plan.final_size();
+    size_t dest_sz = cmap_subset_plan.final_size ();
     void *dest = malloc (dest_sz);
     if (unlikely (!dest)) {
       DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz);
@@ -880,7 +953,7 @@
     }
 
     // all done, write the blob into dest
-    hb_blob_t *cmap_prime = hb_blob_create ((const char *)dest,
+    hb_blob_t *cmap_prime = hb_blob_create ((const char *) dest,
                                             dest_sz,
                                             HB_MEMORY_MODE_READONLY,
                                             dest,
@@ -890,137 +963,149 @@
     return result;
   }
 
+  const CmapSubtable *find_best_subtable (bool *symbol = nullptr) const
+  {
+    if (symbol) *symbol = false;
+
+    const CmapSubtable *subtable;
+
+    /* 32-bit subtables. */
+    if ((subtable = this->find_subtable (3, 10))) return subtable;
+    if ((subtable = this->find_subtable (0, 6))) return subtable;
+    if ((subtable = this->find_subtable (0, 4))) return subtable;
+
+    /* 16-bit subtables. */
+    if ((subtable = this->find_subtable (3, 1))) return subtable;
+    if ((subtable = this->find_subtable (0, 3))) return subtable;
+    if ((subtable = this->find_subtable (0, 2))) return subtable;
+    if ((subtable = this->find_subtable (0, 1))) return subtable;
+    if ((subtable = this->find_subtable (0, 0))) return subtable;
+
+    /* Symbol subtable. */
+    if ((subtable = this->find_subtable (3, 0)))
+    {
+      if (symbol) *symbol = true;
+      return subtable;
+    }
+
+    /* Meh. */
+    return &Null (CmapSubtable);
+  }
+
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
-      this->blob = OT::Sanitizer<OT::cmap>().sanitize (face->reference_table (HB_OT_TAG_cmap));
-      const OT::cmap *cmap = this->blob->as<OT::cmap> ();
-      const OT::CmapSubtable *subtable = nullptr;
-      const OT::CmapSubtableFormat14 *subtable_uvs = nullptr;
-
-      bool symbol = false;
-      /* 32-bit subtables. */
-      if (!subtable) subtable = cmap->find_subtable (3, 10);
-      if (!subtable) subtable = cmap->find_subtable (0, 6);
-      if (!subtable) subtable = cmap->find_subtable (0, 4);
-      /* 16-bit subtables. */
-      if (!subtable) subtable = cmap->find_subtable (3, 1);
-      if (!subtable) subtable = cmap->find_subtable (0, 3);
-      if (!subtable) subtable = cmap->find_subtable (0, 2);
-      if (!subtable) subtable = cmap->find_subtable (0, 1);
-      if (!subtable) subtable = cmap->find_subtable (0, 0);
-      if (!subtable)
+      this->table = hb_sanitize_context_t ().reference_table<cmap> (face);
+      bool symbol;
+      this->subtable = table->find_best_subtable (&symbol);
+      this->subtable_uvs = &Null (CmapSubtableFormat14);
       {
-        subtable = cmap->find_subtable (3, 0);
-        if (subtable) symbol = true;
-      }
-      /* Meh. */
-      if (!subtable) subtable = &Null(OT::CmapSubtable);
-
-      /* UVS subtable. */
-      if (!subtable_uvs)
-      {
-        const OT::CmapSubtable *st = cmap->find_subtable (0, 5);
+        const CmapSubtable *st = table->find_subtable (0, 5);
         if (st && st->u.format == 14)
           subtable_uvs = &st->u.format14;
       }
-      /* Meh. */
-      if (!subtable_uvs) subtable_uvs = &Null(OT::CmapSubtableFormat14);
-
-      this->uvs_table = subtable_uvs;
 
       this->get_glyph_data = subtable;
       if (unlikely (symbol))
       {
-        this->get_glyph_func = get_glyph_from_symbol<OT::CmapSubtable>;
-        this->get_all_codepoints_func = null_get_all_codepoints_func;
+        this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable>;
       } else {
         switch (subtable->u.format) {
         /* Accelerate format 4 and format 12. */
         default:
-          this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
-          this->get_all_codepoints_func = null_get_all_codepoints_func;
+          this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
           break;
         case 12:
-          this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;
-          this->get_all_codepoints_func = get_all_codepoints_from<OT::CmapSubtableFormat12>;
+          this->get_glyph_funcZ = get_glyph_from<CmapSubtableFormat12>;
           break;
         case  4:
           {
             this->format4_accel.init (&subtable->u.format4);
             this->get_glyph_data = &this->format4_accel;
-            this->get_glyph_func = this->format4_accel.get_glyph_func;
-            this->get_all_codepoints_func = this->format4_accel.get_all_codepoints_func;
+            this->get_glyph_funcZ = this->format4_accel.get_glyph_func;
           }
           break;
         }
       }
     }
 
-    inline void fini (void)
-    {
-      hb_blob_destroy (this->blob);
-    }
+    void fini () { this->table.destroy (); }
 
-    inline bool get_nominal_glyph (hb_codepoint_t  unicode,
+    bool get_nominal_glyph (hb_codepoint_t  unicode,
                                    hb_codepoint_t *glyph) const
     {
-      return this->get_glyph_func (this->get_glyph_data, unicode, glyph);
+      if (unlikely (!this->get_glyph_funcZ)) return false;
+      return this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph);
+    }
+    unsigned int get_nominal_glyphs (unsigned int count,
+                                     const hb_codepoint_t *first_unicode,
+                                     unsigned int unicode_stride,
+                                     hb_codepoint_t *first_glyph,
+                                     unsigned int glyph_stride) const
+    {
+      if (unlikely (!this->get_glyph_funcZ)) return 0;
+
+      hb_cmap_get_glyph_func_t get_glyph_funcZ = this->get_glyph_funcZ;
+      const void *get_glyph_data = this->get_glyph_data;
+
+      unsigned int done;
+      for (done = 0;
+           done < count && get_glyph_funcZ (get_glyph_data, *first_unicode, first_glyph);
+           done++)
+      {
+        first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
+        first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+      }
+      return done;
     }
 
-    inline bool get_variation_glyph (hb_codepoint_t  unicode,
-                                     hb_codepoint_t  variation_selector,
-                                     hb_codepoint_t *glyph) const
+    bool get_variation_glyph (hb_codepoint_t  unicode,
+                              hb_codepoint_t  variation_selector,
+                              hb_codepoint_t *glyph) const
     {
-      switch (this->uvs_table->get_glyph_variant (unicode,
-                                                  variation_selector,
-                                                  glyph))
+      switch (this->subtable_uvs->get_glyph_variant (unicode,
+                                                     variation_selector,
+                                                     glyph))
       {
-        case OT::GLYPH_VARIANT_NOT_FOUND:               return false;
-        case OT::GLYPH_VARIANT_FOUND:           return true;
-        case OT::GLYPH_VARIANT_USE_DEFAULT:     break;
+        case GLYPH_VARIANT_NOT_FOUND:   return false;
+        case GLYPH_VARIANT_FOUND:       return true;
+        case GLYPH_VARIANT_USE_DEFAULT: break;
       }
 
       return get_nominal_glyph (unicode, glyph);
     }
 
-    inline void get_all_codepoints (hb_set_t *out) const
+    void collect_unicodes (hb_set_t *out) const
+    {
+      subtable->collect_unicodes (out);
+    }
+    void collect_variation_selectors (hb_set_t *out) const
     {
-      this->get_all_codepoints_func (get_glyph_data, out);
+      subtable_uvs->collect_variation_selectors (out);
+    }
+    void collect_variation_unicodes (hb_codepoint_t variation_selector,
+                                     hb_set_t *out) const
+    {
+      subtable_uvs->collect_variation_unicodes (variation_selector, out);
     }
 
     protected:
     typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
                                               hb_codepoint_t codepoint,
                                               hb_codepoint_t *glyph);
-    typedef void (*hb_cmap_get_all_codepoints_func_t) (const void *obj,
-                                                       hb_set_t *out);
-
-    static inline void null_get_all_codepoints_func (const void *obj, hb_set_t *out)
-    {
-      // NOOP
-    }
 
     template <typename Type>
-    static inline bool get_glyph_from (const void *obj,
-                                       hb_codepoint_t codepoint,
-                                       hb_codepoint_t *glyph)
+    static bool get_glyph_from (const void *obj,
+                                hb_codepoint_t codepoint,
+                                hb_codepoint_t *glyph)
     {
       const Type *typed_obj = (const Type *) obj;
       return typed_obj->get_glyph (codepoint, glyph);
     }
 
     template <typename Type>
-    static inline void get_all_codepoints_from (const void *obj,
-                                                hb_set_t *out)
-    {
-      const Type *typed_obj = (const Type *) obj;
-      typed_obj->get_all_codepoints (out);
-    }
-
-    template <typename Type>
-    static inline bool get_glyph_from_symbol (const void *obj,
+    static bool get_glyph_from_symbol (const void *obj,
                                               hb_codepoint_t codepoint,
                                               hb_codepoint_t *glyph)
     {
@@ -1042,33 +1127,41 @@
     }
 
     private:
-    hb_cmap_get_glyph_func_t get_glyph_func;
-    const void *get_glyph_data;
-    hb_cmap_get_all_codepoints_func_t get_all_codepoints_func;
+    hb_nonnull_ptr_t<const CmapSubtable> subtable;
+    hb_nonnull_ptr_t<const CmapSubtableFormat14> subtable_uvs;
 
-    OT::CmapSubtableFormat4::accelerator_t format4_accel;
+    hb_cmap_get_glyph_func_t get_glyph_funcZ;
+    const void *get_glyph_data;
 
-    const OT::CmapSubtableFormat14 *uvs_table;
-    hb_blob_t *blob;
+    CmapSubtableFormat4::accelerator_t format4_accel;
+
+    hb_blob_ptr_t<cmap> table;
   };
 
   protected:
 
-  inline const CmapSubtable *find_subtable (unsigned int platform_id,
-                                            unsigned int encoding_id) const
+  const CmapSubtable *find_subtable (unsigned int platform_id,
+                                     unsigned int encoding_id) const
   {
     EncodingRecord key;
     key.platformID.set (platform_id);
     key.encodingID.set (encoding_id);
 
-    /* Note: We can use bsearch, but since it has no performance
-     * implications, we use lsearch and as such accept fonts with
-     * unsorted subtable list. */
-    int result = encodingRecord./*bsearch*/lsearch (key);
-    if (result == -1 || !encodingRecord[result].subtable)
+    const EncodingRecord &result = encodingRecord.bsearch (key);
+    if (!result.subtable)
       return nullptr;
 
-    return &(this+encodingRecord[result].subtable);
+    return &(this+result.subtable);
+  }
+
+  public:
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  likely (version == 0) &&
+                  encodingRecord.sanitize (c, this));
   }
 
   protected:
@@ -1079,6 +1172,7 @@
   DEFINE_SIZE_ARRAY (4, encodingRecord);
 };
 
+struct cmap_accelerator_t : cmap::accelerator_t {};
 
 } /* namespace OT */
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cbdt-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cbdt-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,7 @@
 #ifndef HB_OT_COLOR_CBDT_TABLE_HH
 #define HB_OT_COLOR_CBDT_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * CBLC -- Color Bitmap Location
@@ -45,18 +45,18 @@
 
 struct SmallGlyphMetrics
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  inline void get_extents (hb_glyph_extents_t *extents) const
+  void get_extents (hb_glyph_extents_t *extents) const
   {
     extents->x_bearing = bearingX;
     extents->y_bearing = bearingY;
     extents->width = width;
-    extents->height = -height;
+    extents->height = - (hb_position_t) height;
   }
 
   HBUINT8       height;
@@ -79,7 +79,7 @@
 
 struct SBitLineMetrics
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -108,7 +108,7 @@
 
 struct IndexSubtableHeader
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -124,11 +124,11 @@
 template <typename OffsetType>
 struct IndexSubtableFormat1Or3
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
+                  offsetArrayZ.sanitize (c, glyph_count + 1));
   }
 
   bool get_image_data (unsigned int idx,
@@ -144,7 +144,8 @@
   }
 
   IndexSubtableHeader   header;
-  Offset<OffsetType>    offsetArrayZ[VAR];
+  UnsizedArrayOf<Offset<OffsetType> >
+                        offsetArrayZ;
   public:
   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
 };
@@ -154,7 +155,7 @@
 
 struct IndexSubtable
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
   {
     TRACE_SANITIZE (this);
     if (!u.header.sanitize (c)) return_trace (false);
@@ -165,7 +166,7 @@
     }
   }
 
-  inline bool get_extents (hb_glyph_extents_t *extents) const
+  bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const
   {
     switch (u.header.indexFormat) {
     case 2: case 5: /* TODO */
@@ -200,29 +201,28 @@
 
 struct IndexSubtableRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   firstGlyphIndex <= lastGlyphIndex &&
-                  offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
+                  offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1));
   }
 
-  inline bool get_extents (hb_glyph_extents_t *extents) const
+  bool get_extents (hb_glyph_extents_t *extents,
+                    const void *base) const
   {
-    return (this+offsetToSubtable).get_extents (extents);
+    return (base+offsetToSubtable).get_extents (extents);
   }
 
-  bool get_image_data (unsigned int gid,
+  bool get_image_data (unsigned int  gid,
+                       const void   *base,
                        unsigned int *offset,
                        unsigned int *length,
                        unsigned int *format) const
   {
-    if (gid < firstGlyphIndex || gid > lastGlyphIndex)
-    {
-      return false;
-    }
-    return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
+    if (gid < firstGlyphIndex || gid > lastGlyphIndex) return false;
+    return (base+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
                                                    offset, length, format);
   }
 
@@ -237,15 +237,10 @@
 {
   friend struct CBDT;
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
   {
     TRACE_SANITIZE (this);
-    if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count)))
-      return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
-        return_trace (false);
-    return_trace (true);
+    return_trace (indexSubtablesZ.sanitize (c, count, this));
   }
 
   public:
@@ -255,17 +250,14 @@
     {
       unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
       unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
-      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
+      if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex)
         return &indexSubtablesZ[i];
-      }
     }
     return nullptr;
   }
 
   protected:
-  IndexSubtableRecord   indexSubtablesZ[VAR];
-  public:
-  DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
+  UnsizedArrayOf<IndexSubtableRecord>   indexSubtablesZ;
 };
 
 struct BitmapSizeTable
@@ -273,23 +265,25 @@
   friend struct CBLC;
   friend struct CBDT;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
-                  c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) &&
                   horizontal.sanitize (c) &&
                   vertical.sanitize (c));
   }
 
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const
+  const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
+                                         const void *base,
+                                         const void **out_base) const
   {
+    *out_base = &(base+indexSubtableArrayOffset);
     return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
   }
 
   protected:
-  LOffsetTo<IndexSubtableArray>
+  LNNOffsetTo<IndexSubtableArray>
                         indexSubtableArrayOffset;
   HBUINT32              indexTablesSize;
   HBUINT32              numberOfIndexSubtables;
@@ -338,9 +332,9 @@
 {
   friend struct CBDT;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBLC;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -349,25 +343,30 @@
   }
 
   protected:
-  const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
-                                         unsigned int *x_ppem, unsigned int *y_ppem) const
+  const BitmapSizeTable &choose_strike (hb_font_t *font) const
   {
-    /* TODO: Make it possible to select strike. */
+    unsigned count = sizeTables.len;
+    if (unlikely (!count))
+      return Null(BitmapSizeTable);
 
-    unsigned int count = sizeTables.len;
-    for (uint32_t i = 0; i < count; ++i)
+    unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+    if (!requested_ppem)
+      requested_ppem = 1<<30; /* Choose largest strike. */
+    unsigned int best_i = 0;
+    unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY);
+
+    for (unsigned int i = 1; i < count; i++)
     {
-      unsigned int startGlyphIndex = sizeTables.arrayZ[i].startGlyphIndex;
-      unsigned int endGlyphIndex = sizeTables.arrayZ[i].endGlyphIndex;
-      if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
+      unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY);
+      if ((requested_ppem <= ppem && ppem < best_ppem) ||
+          (requested_ppem > best_ppem && ppem > best_ppem))
       {
-        *x_ppem = sizeTables[i].ppemX;
-        *y_ppem = sizeTables[i].ppemY;
-        return sizeTables[i].find_table (glyph, this);
+        best_i = i;
+        best_ppem = ppem;
       }
     }
 
-    return nullptr;
+    return sizeTables[best_i];
   }
 
   protected:
@@ -379,60 +378,42 @@
 
 struct CBDT
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  likely (version.major == 2 || version.major == 3));
-  }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBDT;
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
-      upem = hb_face_get_upem (face);
-
-      cblc_blob = Sanitizer<CBLC>().sanitize (face->reference_table (HB_OT_TAG_CBLC));
-      cbdt_blob = Sanitizer<CBDT>().sanitize (face->reference_table (HB_OT_TAG_CBDT));
-      cbdt_len = hb_blob_get_length (cbdt_blob);
+      cblc = hb_sanitize_context_t().reference_table<CBLC> (face);
+      cbdt = hb_sanitize_context_t().reference_table<CBDT> (face);
 
-      if (hb_blob_get_length (cblc_blob) == 0) {
-        cblc = nullptr;
-        cbdt = nullptr;
-        return;  /* Not a bitmap font. */
-      }
-      cblc = cblc_blob->as<CBLC> ();
-      cbdt = cbdt_blob->as<CBDT> ();
-
+      upem = hb_face_get_upem (face);
     }
 
-    inline void fini (void)
+    void fini ()
     {
-      hb_blob_destroy (this->cblc_blob);
-      hb_blob_destroy (this->cbdt_blob);
+      this->cblc.destroy ();
+      this->cbdt.destroy ();
     }
 
-    inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+    bool get_extents (hb_font_t *font, hb_codepoint_t glyph,
+                      hb_glyph_extents_t *extents) const
     {
-      unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
-
-      if (!cblc)
-        return false;  // Not a color bitmap font.
-
-      const IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem);
-      if (!subtable_record || !x_ppem || !y_ppem)
+      const void *base;
+      const BitmapSizeTable &strike = this->cblc->choose_strike (font);
+      const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
+      if (!subtable_record || !strike.ppemX || !strike.ppemY)
         return false;
 
-      if (subtable_record->get_extents (extents))
+      if (subtable_record->get_extents (extents, base))
         return true;
 
       unsigned int image_offset = 0, image_length = 0, image_format = 0;
-      if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format))
+      if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
         return false;
 
       {
+        unsigned int cbdt_len = cbdt.get_length ();
         if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
           return false;
 
@@ -441,98 +422,114 @@
           case 17: {
             if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
               return false;
-
             const GlyphBitmapDataFormat17& glyphFormat17 =
                 StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
             glyphFormat17.glyphMetrics.get_extents (extents);
+            break;
           }
-          break;
+          case 18: {
+            if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
+              return false;
+            const GlyphBitmapDataFormat18& glyphFormat18 =
+                StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
+            glyphFormat18.glyphMetrics.get_extents (extents);
+            break;
+          }
           default:
             // TODO: Support other image formats.
             return false;
         }
       }
 
-      /* Convert to the font units. */
-      extents->x_bearing *= upem / (float) x_ppem;
-      extents->y_bearing *= upem / (float) y_ppem;
-      extents->width *= upem / (float) x_ppem;
-      extents->height *= upem / (float) y_ppem;
+      /* Convert to font units. */
+      double x_scale = upem / (double) strike.ppemX;
+      double y_scale = upem / (double) strike.ppemY;
+      extents->x_bearing = round (extents->x_bearing * x_scale);
+      extents->y_bearing = round (extents->y_bearing * y_scale);
+      extents->width = round (extents->width * x_scale);
+      extents->height = round (extents->height * y_scale);
 
       return true;
     }
 
-    inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
-        unsigned int group, unsigned int gid)) const
+    hb_blob_t* reference_png (hb_font_t      *font,
+                                     hb_codepoint_t  glyph) const
     {
-      if (!cblc)
-        return;  // Not a color bitmap font.
+      const void *base;
+      const BitmapSizeTable &strike = this->cblc->choose_strike (font);
+      const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
+      if (!subtable_record || !strike.ppemX || !strike.ppemY)
+        return hb_blob_get_empty ();
 
-      for (unsigned int i = 0; i < cblc->sizeTables.len; ++i)
+      unsigned int image_offset = 0, image_length = 0, image_format = 0;
+      if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
+        return hb_blob_get_empty ();
+
       {
-        const BitmapSizeTable &sizeTable = cblc->sizeTables[i];
-        const IndexSubtableArray &subtable_array = cblc+sizeTable.indexSubtableArrayOffset;
-        for (unsigned int j = 0; j < sizeTable.numberOfIndexSubtables; ++j)
-        {
-          const IndexSubtableRecord &subtable_record = subtable_array.indexSubtablesZ[j];
-          for (unsigned int gid = subtable_record.firstGlyphIndex;
-                gid <= subtable_record.lastGlyphIndex; ++gid)
-          {
-            unsigned int image_offset = 0, image_length = 0, image_format = 0;
-
-            if (!subtable_record.get_image_data (gid,
-                  &image_offset, &image_length, &image_format))
-              continue;
+        unsigned int cbdt_len = cbdt.get_length ();
+        if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
+          return hb_blob_get_empty ();
 
-            switch (image_format)
-            {
-            case 17: {
-              const GlyphBitmapDataFormat17& glyphFormat17 =
-                StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat17.data.arrayZ,
-                glyphFormat17.data.len, i, gid);
-            }
-            break;
-            case 18: {
-              const GlyphBitmapDataFormat18& glyphFormat18 =
-                StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat18.data.arrayZ,
-                glyphFormat18.data.len, i, gid);
-            }
-            break;
-            case 19: {
-              const GlyphBitmapDataFormat19& glyphFormat19 =
-                StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
-              callback ((const uint8_t *) &glyphFormat19.data.arrayZ,
-                glyphFormat19.data.len, i, gid);
-            }
-            break;
-            default:
-              continue;
-            }
+        switch (image_format)
+        {
+          case 17: {
+            if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
+              return hb_blob_get_empty ();
+            const GlyphBitmapDataFormat17& glyphFormat17 =
+              StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
+            return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                            image_offset + GlyphBitmapDataFormat17::min_size,
+                                            glyphFormat17.data.len);
+          }
+          case 18: {
+            if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
+              return hb_blob_get_empty ();
+            const GlyphBitmapDataFormat18& glyphFormat18 =
+              StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
+            return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                            image_offset + GlyphBitmapDataFormat18::min_size,
+                                            glyphFormat18.data.len);
+          }
+          case 19: {
+            if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
+              return hb_blob_get_empty ();
+            const GlyphBitmapDataFormat19& glyphFormat19 =
+              StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
+            return hb_blob_create_sub_blob (cbdt.get_blob (),
+                                            image_offset + GlyphBitmapDataFormat19::min_size,
+                                            glyphFormat19.data.len);
           }
         }
       }
+
+      return hb_blob_get_empty ();
     }
 
+    bool has_data () const { return cbdt.get_length (); }
+
     private:
-    hb_blob_t *cblc_blob;
-    hb_blob_t *cbdt_blob;
-    const CBLC *cblc;
-    const CBDT *cbdt;
+    hb_blob_ptr_t<CBLC> cblc;
+    hb_blob_ptr_t<CBDT> cbdt;
 
-    unsigned int cbdt_len;
     unsigned int upem;
   };
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  likely (version.major == 2 || version.major == 3));
+  }
 
   protected:
-  FixedVersion<>        version;
-  HBUINT8               dataZ[VAR];
+  FixedVersion<>                version;
+  UnsizedArrayOf<HBUINT8>       dataZ;
   public:
   DEFINE_SIZE_ARRAY(4, dataZ);
 };
 
+struct CBDT_accelerator_t : CBDT::accelerator_t {};
+
 } /* namespace OT */
 
 #endif /* HB_OT_COLOR_CBDT_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-colr-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-colr-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_COLR_TABLE_HH
 #define HB_OT_COLOR_COLR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * COLR -- Color
@@ -39,55 +39,82 @@
 
 struct LayerRecord
 {
-  friend struct COLR;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  protected:
-  GlyphID       glyphid;        /* Glyph ID of layer glyph */
-  HBUINT16      colorIdx;       /* Index value to use with a selected color palette */
+  public:
+  GlyphID       glyphId;        /* Glyph ID of layer glyph */
+  Index         colorIdx;       /* Index value to use with a
+                                 * selected color palette.
+                                 * An index value of 0xFFFF
+                                 * is a special case indicating
+                                 * that the text foreground
+                                 * color (defined by a
+                                 * higher-level client) should
+                                 * be used and shall not be
+                                 * treated as actual index
+                                 * into CPAL ColorRecord array. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct BaseGlyphRecord
 {
-  friend struct COLR;
+  int cmp (hb_codepoint_t g) const
+  { return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this)));
   }
 
-  inline int cmp (hb_codepoint_t g) const {
-    return g < glyphid ? -1 : g > glyphid ? 1 : 0;
-  }
-
-  protected:
-  GlyphID       glyphid;        /* Glyph ID of reference glyph */
-  HBUINT16      firstLayerIdx;  /* Index to the layer record */
-  HBUINT16      numLayers;      /* Number of color layers associated with this glyph */
+  public:
+  GlyphID       glyphId;        /* Glyph ID of reference glyph */
+  HBUINT16      firstLayerIdx;  /* Index (from beginning of
+                                 * the Layer Records) to the
+                                 * layer record. There will be
+                                 * numLayers consecutive entries
+                                 * for this base glyph. */
+  HBUINT16      numLayers;      /* Number of color layers
+                                 * associated with this glyph */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
-static int compare_bgr (const void *pa, const void *pb)
-{
-  const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
-  const BaseGlyphRecord *b = (const BaseGlyphRecord *) pb;
-  return b->cmp (*a);
-}
-
 struct COLR
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_COLR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_COLR;
+
+  bool has_data () const { return numBaseGlyphs; }
+
+  unsigned int get_glyph_layers (hb_codepoint_t       glyph,
+                                 unsigned int         start_offset,
+                                 unsigned int        *count, /* IN/OUT.  May be NULL. */
+                                 hb_ot_color_layer_t *layers /* OUT.     May be NULL. */) const
+  {
+    const BaseGlyphRecord &record = (this+baseGlyphsZ).bsearch (numBaseGlyphs, glyph);
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+    hb_array_t<const LayerRecord> all_layers ((this+layersZ).arrayZ, numLayers);
+    hb_array_t<const LayerRecord> glyph_layers = all_layers.sub_array (record.firstLayerIdx,
+                                                                       record.numLayers);
+    if (count)
+    {
+      hb_array_t<const LayerRecord> segment_layers = glyph_layers.sub_array (start_offset, *count);
+      *count = segment_layers.length;
+      for (unsigned int i = 0; i < segment_layers.length; i++)
+      {
+        layers[i].glyph = segment_layers.arrayZ[i].glyphId;
+        layers[i].color_index = segment_layers.arrayZ[i].colorIdx;
+      }
+    }
+    return glyph_layers.length;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (likely (c->check_struct (this) &&
@@ -95,45 +122,14 @@
                           (this+layersZ).sanitize (c, numLayers)));
   }
 
-  inline bool get_base_glyph_record (hb_codepoint_t glyph_id,
-                                     unsigned int *first_layer /* OUT */,
-                                     unsigned int *num_layers /* OUT */) const
-  {
-    const BaseGlyphRecord* record;
-    record = (BaseGlyphRecord *) bsearch (&glyph_id, &(this+baseGlyphsZ), numBaseGlyphs,
-                                          sizeof (BaseGlyphRecord), compare_bgr);
-    if (unlikely (!record))
-      return false;
-
-    *first_layer = record->firstLayerIdx;
-    *num_layers = record->numLayers;
-    return true;
-  }
-
-  inline bool get_layer_record (unsigned int record,
-                                hb_codepoint_t *glyph_id /* OUT */,
-                                unsigned int *palette_index /* OUT */) const
-  {
-    if (unlikely (record >= numLayers))
-    {
-      *glyph_id = 0;
-      *palette_index = 0xFFFF;
-      return false;
-    }
-    const LayerRecord &layer = (this+layersZ)[record];
-    *glyph_id = layer.glyphid;
-    *palette_index = layer.colorIdx;
-    return true;
-  }
-
   protected:
-  HBUINT16      version;        /* Table version number */
-  HBUINT16      numBaseGlyphs;  /* Number of Base Glyph Records */
-  LOffsetTo<UnsizedArrayOf<BaseGlyphRecord> >
+  HBUINT16      version;        /* Table version number (starts at 0). */
+  HBUINT16      numBaseGlyphs;  /* Number of Base Glyph Records. */
+  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord> >
                 baseGlyphsZ;    /* Offset to Base Glyph records. */
-  LOffsetTo<UnsizedArrayOf<LayerRecord> >
-                layersZ;        /* Offset to Layer Records */
-  HBUINT16      numLayers;      /* Number of Layer Records */
+  LNNOffsetTo<UnsizedArrayOf<LayerRecord> >
+                layersZ;        /* Offset to Layer Records. */
+  HBUINT16      numLayers;      /* Number of Layer Records. */
   public:
   DEFINE_SIZE_STATIC (14);
 };
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cpal-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-cpal-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -28,54 +28,9 @@
 #ifndef HB_OT_COLOR_CPAL_TABLE_HH
 #define HB_OT_COLOR_CPAL_TABLE_HH
 
-#include "hb-open-type-private.hh"
-
-
-/*
- * Following parts to be moved to a public header.
- */
-
-/**
- * hb_ot_color_t:
- * ARGB data type for holding color values.
- *
- * Since: REPLACEME
- */
-typedef uint32_t hb_ot_color_t;
-
-
-/**
- * hb_ot_color_palette_flags_t:
- * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette.
- * @HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND: flag indicating that the color palette is suitable for rendering text on light background.
- * @HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND: flag indicating that the color palette is suitable for rendering text on dark background.
- *
- * Since: REPLACEME
- */
-typedef enum { /*< flags >*/
-  HB_OT_COLOR_PALETTE_FLAG_DEFAULT = 0x00000000u,
-  HB_OT_COLOR_PALETTE_FLAG_FOR_LIGHT_BACKGROUND = 0x00000001u,
-  HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u,
-} hb_ot_color_palette_flags_t;
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_count (hb_face_t *face);
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette);
-
-// HB_EXTERN hb_ot_color_palette_flags_t
-// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette);
-
-// HB_EXTERN unsigned int
-// hb_ot_color_get_palette_colors (hb_face_t       *face,
-//                              unsigned int     palette, /* default=0 */
-//                              unsigned int     start_offset,
-//                              unsigned int    *color_count /* IN/OUT */,
-//                              hb_ot_color_t   *colors /* OUT */);
-
-
-
+#include "hb-open-type.hh"
+#include "hb-ot-color.h"
+#include "hb-ot-name.h"
 
 
 /*
@@ -92,43 +47,57 @@
 {
   friend struct CPAL;
 
-  inline bool
-  sanitize (hb_sanitize_context_t *c, const void *base, unsigned int palettes) const
+  private:
+  hb_ot_color_palette_flags_t get_palette_flags (const void *base,
+                                                 unsigned int palette_index,
+                                                 unsigned int palette_count) const
+  {
+    if (!paletteFlagsZ) return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
+    return (hb_ot_color_palette_flags_t) (uint32_t)
+           (base+paletteFlagsZ).as_array (palette_count)[palette_index];
+  }
+
+  hb_ot_name_id_t get_palette_name_id (const void *base,
+                                       unsigned int palette_index,
+                                       unsigned int palette_count) const
+  {
+    if (!paletteLabelsZ) return HB_OT_NAME_ID_INVALID;
+    return (base+paletteLabelsZ).as_array (palette_count)[palette_index];
+  }
+
+  hb_ot_name_id_t get_color_name_id (const void *base,
+                                     unsigned int color_index,
+                                     unsigned int color_count) const
+  {
+    if (!colorLabelsZ) return HB_OT_NAME_ID_INVALID;
+    return (base+colorLabelsZ).as_array (color_count)[color_index];
+  }
+
+  public:
+  bool sanitize (hb_sanitize_context_t *c,
+                 const void *base,
+                 unsigned int palette_count,
+                 unsigned int color_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  (base+paletteFlagsZ).sanitize (c, palettes) &&
-                  (base+paletteLabelZ).sanitize (c, palettes) &&
-                  (base+paletteEntryLabelZ).sanitize (c, palettes));
-  }
-
-  private:
-  inline hb_ot_color_palette_flags_t
-  get_palette_flags (const void *base, unsigned int palette) const
-  {
-    // range checked at the CPAL caller
-    return (hb_ot_color_palette_flags_t) (uint32_t) (base+paletteFlagsZ)[palette];
-  }
-
-  inline unsigned int
-  get_palette_name_id (const void *base, unsigned int palette) const
-  {
-    // range checked at the CPAL caller
-    return (base+paletteLabelZ)[palette];
+                  (!paletteFlagsZ  || (base+paletteFlagsZ).sanitize (c, palette_count)) &&
+                  (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) &&
+                  (!colorLabelsZ   || (base+colorLabelsZ).sanitize (c, color_count)));
   }
 
   protected:
-  LOffsetTo<UnsizedArrayOf<HBUINT32> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT32> >
                 paletteFlagsZ;          /* Offset from the beginning of CPAL table to
                                          * the Palette Type Array. Set to 0 if no array
                                          * is provided. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16> >
-                paletteLabelZ;          /* Offset from the beginning of CPAL table to
-                                         * the Palette Labels Array. Set to 0 if no
+  LNNOffsetTo<UnsizedArrayOf<NameID> >
+                paletteLabelsZ;         /* Offset from the beginning of CPAL table to
+                                         * the palette labels array. Set to 0 if no
                                          * array is provided. */
-  LOffsetTo<UnsizedArrayOf<HBUINT16> >
-                paletteEntryLabelZ;     /* Offset from the beginning of CPAL table to
-                                         * the Palette Entry Label Array. Set to 0
+  LNNOffsetTo<UnsizedArrayOf<NameID> >
+                colorLabelsZ;           /* Offset from the beginning of CPAL table to
+                                         * the color labels array. Set to 0
                                          * if no array is provided. */
   public:
   DEFINE_SIZE_STATIC (12);
@@ -138,76 +107,76 @@
 
 struct CPAL
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_CPAL;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_CPAL;
+
+  bool has_data () const { return numPalettes; }
+
+  unsigned int get_size () const
+  { return min_size + numPalettes * sizeof (colorRecordIndicesZ[0]); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this) &&   // it checks colorRecordIndices also
-                                                // see #get_size
-                    (this+colorRecordsZ).sanitize (c, numColorRecords))))
-      return_trace (false);
+  unsigned int get_palette_count () const { return numPalettes; }
+  unsigned int get_color_count () const   { return numColors; }
+
+  hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette_index) const
+  { return v1 ().get_palette_flags (this, palette_index, numPalettes); }
+
+  hb_ot_name_id_t get_palette_name_id (unsigned int palette_index) const
+  { return v1 ().get_palette_name_id (this, palette_index, numPalettes); }
+
+  hb_ot_name_id_t get_color_name_id (unsigned int color_index) const
+  { return v1 ().get_color_name_id (this, color_index, numColors); }
 
-    // Check for indices sanity so no need for doing it runtime
-    for (unsigned int i = 0; i < numPalettes; ++i)
-      if (unlikely (colorRecordIndicesZ[i] + numPaletteEntries > numColorRecords))
-        return_trace (false);
-
-    // If version is zero, we are done here; otherwise we need to check tail also
-    if (version == 0)
-      return_trace (true);
-
-    const CPALV1Tail &v1 = StructAfter<CPALV1Tail> (*this);
-    return_trace (likely (v1.sanitize (c, this, numPalettes)));
-  }
-
-  inline unsigned int get_size (void) const
+  unsigned int get_palette_colors (unsigned int  palette_index,
+                                   unsigned int  start_offset,
+                                   unsigned int *color_count, /* IN/OUT.  May be NULL. */
+                                   hb_color_t   *colors       /* OUT.     May be NULL. */) const
   {
-    return min_size + numPalettes * sizeof (HBUINT16);
+    if (unlikely (palette_index >= numPalettes))
+    {
+      if (color_count) *color_count = 0;
+      return 0;
+    }
+    unsigned int start_index = colorRecordIndicesZ[palette_index];
+    hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
+    hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index,
+                                                                       numColors);
+    if (color_count)
+    {
+      hb_array_t<const BGRAColor> segment_colors = palette_colors.sub_array (start_offset, *color_count);
+      /* Always return numColors colors per palette even if it has out-of-bounds start index. */
+      unsigned int count = MIN<unsigned int> (MAX<int> (numColors - start_offset, 0), *color_count);
+      *color_count = count;
+      for (unsigned int i = 0; i < count; i++)
+        colors[i] = segment_colors[i]; /* Bound-checked read. */
+    }
+    return numColors;
   }
 
-  inline hb_ot_color_palette_flags_t get_palette_flags (unsigned int palette) const
+  private:
+  const CPALV1Tail& v1 () const
   {
-    if (unlikely (version == 0 || palette >= numPalettes))
-      return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
-
-    const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
-    return cpal1.get_palette_flags (this, palette);
+    if (version == 0) return Null(CPALV1Tail);
+    return StructAfter<CPALV1Tail> (*this);
   }
 
-  inline unsigned int get_palette_name_id (unsigned int palette) const
-  {
-    if (unlikely (version == 0 || palette >= numPalettes))
-      return 0xFFFF;
-
-    const CPALV1Tail& cpal1 = StructAfter<CPALV1Tail> (*this);
-    return cpal1.get_palette_name_id (this, palette);
-  }
-
-  inline unsigned int get_palette_count () const
+  public:
+  bool sanitize (hb_sanitize_context_t *c) const
   {
-    return numPalettes;
-  }
-
-  inline hb_ot_color_t
-  get_color_record_argb (unsigned int color_index, unsigned int palette) const
-  {
-    if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes))
-      return 0;
-
-    // No need for more range check as it is already done on #sanitize
-    const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ;
-    return color_records[colorRecordIndicesZ[palette] + color_index];
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  (this+colorRecordsZ).sanitize (c, numColorRecords) &&
+                  colorRecordIndicesZ.sanitize (c, numPalettes) &&
+                  (version == 0 || v1 ().sanitize (c, this, numPalettes, numColors)));
   }
 
   protected:
   HBUINT16      version;                /* Table version number */
   /* Version 0 */
-  HBUINT16      numPaletteEntries;      /* Number of palette entries in each palette. */
+  HBUINT16      numColors;              /* Number of colors in each palette. */
   HBUINT16      numPalettes;            /* Number of palettes in the table. */
   HBUINT16      numColorRecords;        /* Total number of color records, combined for
                                          * all palettes. */
-  LOffsetTo<UnsizedArrayOf<BGRAColor> >
+  LNNOffsetTo<UnsizedArrayOf<BGRAColor> >
                 colorRecordsZ;          /* Offset from the beginning of CPAL table to
                                          * the first ColorRecord. */
   UnsizedArrayOf<HBUINT16>
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-sbix-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-sbix-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_SBIX_TABLE_HH
 #define HB_OT_COLOR_SBIX_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * sbix -- Standard Bitmap Graphics
@@ -62,19 +62,65 @@
 
 struct SBIXStrike
 {
-  friend struct sbix;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  imageOffsetsZ.sanitize_shallow (c, c->num_glyphs + 1));
+                  imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
   }
 
-  protected:
+  hb_blob_t *get_glyph_blob (unsigned int  glyph_id,
+                             hb_blob_t    *sbix_blob,
+                             hb_tag_t      file_type,
+                             int          *x_offset,
+                             int          *y_offset,
+                             unsigned int  num_glyphs,
+                             unsigned int *strike_ppem) const
+  {
+    if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */
+
+    unsigned int retry_count = 8;
+    unsigned int sbix_len = sbix_blob->length;
+    unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data;
+    assert (strike_offset < sbix_len);
+
+  retry:
+    if (unlikely (glyph_id >= num_glyphs ||
+                  imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] ||
+                  imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size ||
+                  (unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset))
+      return hb_blob_get_empty ();
+
+    unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size;
+    unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size;
+
+    const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]);
+
+    if (glyph->graphicType == HB_TAG ('d','u','p','e'))
+    {
+      if (glyph_length >= 2)
+      {
+        glyph_id = *((HBUINT16 *) &glyph->data);
+        if (retry_count--)
+          goto retry;
+      }
+      return hb_blob_get_empty ();
+    }
+
+    if (unlikely (file_type != glyph->graphicType))
+      return hb_blob_get_empty ();
+
+    if (strike_ppem) *strike_ppem = ppem;
+    if (x_offset) *x_offset = glyph->xOffset;
+    if (y_offset) *y_offset = glyph->yOffset;
+    return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
+  }
+
+  public:
   HBUINT16      ppem;           /* The PPEM size for which this strike was designed. */
   HBUINT16      resolution;     /* The device pixel density (in PPI) for which this
                                  * strike was designed. (E.g., 96 PPI, 192 PPI.) */
+  protected:
   UnsizedArrayOf<LOffsetTo<SBIXGlyph> >
                 imageOffsetsZ;  /* Offset from the beginning of the strike data header
                                  * to bitmap data for an individual glyph ID. */
@@ -84,70 +130,157 @@
 
 struct sbix
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_sbix;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_sbix;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) && strikes.sanitize (c, this)));
-  }
+  bool has_data () const { return version; }
+
+  const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; }
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
-      num_glyphs = hb_face_get_glyph_count (face);
+      table = hb_sanitize_context_t().reference_table<sbix> (face);
+      num_glyphs = face->get_num_glyphs ();
+    }
+    void fini () { table.destroy (); }
 
-      OT::Sanitizer<OT::sbix> sanitizer;
-      sanitizer.set_num_glyphs (num_glyphs);
-      sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix));
-      sbix_len = hb_blob_get_length (sbix_blob);
-      sbix_table = sbix_blob->as<OT::sbix> ();
+    bool has_data () const { return table->has_data (); }
 
+    bool get_extents (hb_font_t          *font,
+                      hb_codepoint_t      glyph,
+                      hb_glyph_extents_t *extents) const
+    {
+      /* We only support PNG right now, and following function checks type. */
+      return get_png_extents (font, glyph, extents);
     }
 
-    inline void fini (void)
-    {
-      hb_blob_destroy (sbix_blob);
-    }
-
-    inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
-                                        unsigned int group, unsigned int gid)) const
+    hb_blob_t *reference_png (hb_font_t      *font,
+                              hb_codepoint_t  glyph_id,
+                              int            *x_offset,
+                              int            *y_offset,
+                              unsigned int   *available_ppem) const
     {
-      for (unsigned group = 0; group < sbix_table->strikes.len; ++group)
-      {
-        const SBIXStrike &strike = sbix_table->strikes[group](sbix_table);
-        for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph)
-          if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0)
-          {
-            const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike);
-            callback ((const uint8_t*) &sbixGlyph.data,
-                      strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8,
-                      group, glyph);
-          }
-      }
+      return choose_strike (font).get_glyph_blob (glyph_id, table.get_blob (),
+                                                  HB_TAG ('p','n','g',' '),
+                                                  x_offset, y_offset,
+                                                  num_glyphs, available_ppem);
     }
 
     private:
-    hb_blob_t *sbix_blob;
-    const sbix *sbix_table;
+
+    const SBIXStrike &choose_strike (hb_font_t *font) const
+    {
+      unsigned count = table->strikes.len;
+      if (unlikely (!count))
+        return Null(SBIXStrike);
+
+      unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+      if (!requested_ppem)
+        requested_ppem = 1<<30; /* Choose largest strike. */
+      /* TODO Add DPI sensitivity as well? */
+      unsigned int best_i = 0;
+      unsigned int best_ppem = table->get_strike (0).ppem;
+
+      for (unsigned int i = 1; i < count; i++)
+      {
+        unsigned int ppem = (table->get_strike (i)).ppem;
+        if ((requested_ppem <= ppem && ppem < best_ppem) ||
+            (requested_ppem > best_ppem && ppem > best_ppem))
+        {
+          best_i = i;
+          best_ppem = ppem;
+        }
+      }
+
+      return table->get_strike (best_i);
+    }
+
+    struct PNGHeader
+    {
+      HBUINT8   signature[8];
+      struct
+      {
+        struct
+        {
+          HBUINT32      length;
+          Tag           type;
+        }               header;
+        HBUINT32        width;
+        HBUINT32        height;
+        HBUINT8         bitDepth;
+        HBUINT8         colorType;
+        HBUINT8         compressionMethod;
+        HBUINT8         filterMethod;
+        HBUINT8         interlaceMethod;
+      } IHDR;
 
-    unsigned int sbix_len;
+      public:
+      DEFINE_SIZE_STATIC (29);
+    };
+
+    bool get_png_extents (hb_font_t          *font,
+                          hb_codepoint_t      glyph,
+                          hb_glyph_extents_t *extents) const
+    {
+      /* Following code is safe to call even without data.
+       * But faster to short-circuit. */
+      if (!has_data ())
+        return false;
+
+      int x_offset = 0, y_offset = 0;
+      unsigned int strike_ppem = 0;
+      hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
+
+      const PNGHeader &png = *blob->as<PNGHeader>();
+
+      extents->x_bearing = x_offset;
+      extents->y_bearing = y_offset;
+      extents->width     = png.IHDR.width;
+      extents->height    = png.IHDR.height;
+
+      /* Convert to font units. */
+      if (strike_ppem)
+      {
+        double scale = font->face->get_upem () / (double) strike_ppem;
+        extents->x_bearing = round (extents->x_bearing * scale);
+        extents->y_bearing = round (extents->y_bearing * scale);
+        extents->width = round (extents->width * scale);
+        extents->height = round (extents->height * scale);
+      }
+
+      hb_blob_destroy (blob);
+
+      return strike_ppem;
+    }
+
+    private:
+    hb_blob_ptr_t<sbix> table;
+
     unsigned int num_glyphs;
+  };
 
-  };
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          version >= 1 &&
+                          strikes.sanitize (c, this)));
+  }
 
   protected:
   HBUINT16      version;        /* Table version number — set to 1 */
   HBUINT16      flags;          /* Bit 0: Set to 1. Bit 1: Draw outlines.
                                  * Bits 2 to 15: reserved (set to 0). */
-  LArrayOf<LOffsetTo<SBIXStrike> >
+  LOffsetLArrayOf<SBIXStrike>
                 strikes;        /* Offsets from the beginning of the 'sbix'
                                  * table to data for each individual bitmap strike. */
   public:
   DEFINE_SIZE_ARRAY (8, strikes);
 };
 
+struct sbix_accelerator_t : sbix::accelerator_t {};
+
 } /* namespace OT */
 
 #endif /* HB_OT_COLOR_SBIX_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-svg-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-svg-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -25,7 +25,7 @@
 #ifndef HB_OT_COLOR_SVG_TABLE_HH
 #define HB_OT_COLOR_SVG_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * SVG -- SVG (Scalable Vector Graphics)
@@ -40,13 +40,21 @@
 
 struct SVGDocumentIndexEntry
 {
-  friend struct SVG;
+  int cmp (hb_codepoint_t g) const
+  { return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void* base) const
+  hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
+  {
+    return hb_blob_create_sub_blob (svg_blob,
+                                    index_offset + (unsigned int) svgDoc,
+                                    svgDocLength);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  (base+svgDoc).sanitize (c, svgDocLength));
+                  svgDoc.sanitize (c, base, svgDocLength));
   }
 
   protected:
@@ -54,91 +62,62 @@
                                  * this index entry. */
   HBUINT16      endGlyphID;     /* The last glyph ID in the range described by
                                  * this index entry. Must be >= startGlyphID. */
-  LOffsetTo<UnsizedArrayOf<HBUINT8> >
+  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
                 svgDoc;         /* Offset from the beginning of the SVG Document Index
                                  * to an SVG document. Must be non-zero. */
-  HBUINT32 svgDocLength;        /* Length of the SVG document.
+  HBUINT32      svgDocLength;   /* Length of the SVG document.
                                  * Must be non-zero. */
   public:
   DEFINE_SIZE_STATIC (12);
 };
 
-struct SVGDocumentIndex
-{
-  friend struct SVG;
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  entries.sanitize (c, this));
-  }
-
-  protected:
-  ArrayOf<SVGDocumentIndexEntry>
-                entries;        /* Array of SVG Document Index Entries. */
-  public:
-  DEFINE_SIZE_ARRAY (2, entries);
-};
-
 struct SVG
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_SVG;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_SVG;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (likely (c->check_struct (this) &&
-                          (this+svgDocIndex).sanitize (c)));
-  }
+  bool has_data () const { return svgDocEntries; }
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
+    { table = hb_sanitize_context_t().reference_table<SVG> (face); }
+    void fini () { table.destroy (); }
+
+    hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
     {
-      OT::Sanitizer<OT::SVG> sanitizer;
-      svg_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SVG));
-      svg_len = hb_blob_get_length (svg_blob);
-      svg = svg_blob->as<OT::SVG> ();
-
-    }
-
-    inline void fini (void)
-    {
-      hb_blob_destroy (svg_blob);
+      return table->get_glyph_entry (glyph_id).reference_blob (table.get_blob (),
+                                                               table->svgDocEntries);
     }
 
-    inline void
-    dump (void (*callback) (const uint8_t* data, unsigned int length,
-                            unsigned int start_glyph, unsigned int end_glyph)) const
-    {
-      const SVGDocumentIndex &index = svg+svg->svgDocIndex;
-      const ArrayOf<SVGDocumentIndexEntry> &entries = index.entries;
-      for (unsigned int i = 0; i < entries.len; ++i)
-      {
-        const SVGDocumentIndexEntry &entry = entries[i];
-        callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength,
-                                                  entry.startGlyphID, entry.endGlyphID);
-      }
-    }
+    bool has_data () const { return table->has_data (); }
 
     private:
-    hb_blob_t *svg_blob;
-    const SVG *svg;
+    hb_blob_ptr_t<SVG> table;
+  };
+
+  const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
+  { return (this+svgDocEntries).bsearch (glyph_id); }
 
-    unsigned int svg_len;
-  };
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (this+svgDocEntries).sanitize_shallow (c)));
+  }
 
   protected:
   HBUINT16      version;        /* Table version (starting at 0). */
-  LOffsetTo<SVGDocumentIndex>
-                svgDocIndex;    /* Offset (relative to the start of the SVG table) to the
+  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry> >
+                svgDocEntries;  /* Offset (relative to the start of the SVG table) to the
                                  * SVG Documents Index. Must be non-zero. */
+                                /* Array of SVG Document Index Entries. */
   HBUINT32      reserved;       /* Set to 0. */
   public:
   DEFINE_SIZE_STATIC (10);
 };
 
+struct SVG_accelerator_t : SVG::accelerator_t {};
+
 } /* namespace OT */
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,299 @@
+/*
+ * Copyright © 2016  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Sascha Brawer, Behdad Esfahbod
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-color-cbdt-table.hh"
+#include "hb-ot-color-colr-table.hh"
+#include "hb-ot-color-cpal-table.hh"
+#include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-svg-table.hh"
+#include "hb-ot-face.hh"
+#include "hb-ot.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "hb-ot-layout.hh"
+
+
+/**
+ * SECTION:hb-ot-color
+ * @title: hb-ot-color
+ * @short_description: OpenType Color Fonts
+ * @include: hb-ot.h
+ *
+ * Functions for fetching color-font information from OpenType font faces.
+ **/
+
+
+/*
+ * CPAL
+ */
+
+
+/**
+ * hb_ot_color_has_palettes:
+ * @face: a font face.
+ *
+ * Returns: whether CPAL table is available.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_palettes (hb_face_t *face)
+{
+  return face->table.CPAL->has_data ();
+}
+
+/**
+ * hb_ot_color_palette_get_count:
+ * @face: a font face.
+ *
+ * Returns: the number of color palettes in @face, or zero if @face has
+ * no colors.
+ *
+ * Since: 2.1.0
+ */
+unsigned int
+hb_ot_color_palette_get_count (hb_face_t *face)
+{
+  return face->table.CPAL->get_palette_count ();
+}
+
+/**
+ * hb_ot_color_palette_get_name_id:
+ * @face:    a font face.
+ * @palette_index: the index of the color palette whose name is being requested.
+ *
+ * Retrieves the name id of a color palette. For example, a color font can
+ * have themed palettes like "Spring", "Summer", "Fall", and "Winter".
+ *
+ * Returns: an identifier within @face's `name` table.
+ * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
+ *
+ * Since: 2.1.0
+ */
+hb_ot_name_id_t
+hb_ot_color_palette_get_name_id (hb_face_t *face,
+                                 unsigned int palette_index)
+{
+  return face->table.CPAL->get_palette_name_id (palette_index);
+}
+
+/**
+ * hb_ot_color_palette_color_get_name_id:
+ * @face:        a font face.
+ * @color_index: palette entry index.
+ *
+ * Returns: Name ID associated with a palette entry, e.g. eye color
+ *
+ * Since: 2.1.0
+ */
+hb_ot_name_id_t
+hb_ot_color_palette_color_get_name_id (hb_face_t *face,
+                                       unsigned int color_index)
+{
+  return face->table.CPAL->get_color_name_id (color_index);
+}
+
+/**
+ * hb_ot_color_palette_get_flags:
+ * @face:          a font face
+ * @palette_index: the index of the color palette whose flags are being requested
+ *
+ * Returns: the flags for the requested color palette.
+ *
+ * Since: 2.1.0
+ */
+hb_ot_color_palette_flags_t
+hb_ot_color_palette_get_flags (hb_face_t *face,
+                               unsigned int palette_index)
+{
+  return face->table.CPAL->get_palette_flags (palette_index);
+}
+
+/**
+ * hb_ot_color_palette_get_colors:
+ * @face:         a font face.
+ * @palette_index:the index of the color palette whose colors
+ *                are being requested.
+ * @start_offset: the index of the first color being requested.
+ * @color_count:  (inout) (optional): on input, how many colors
+ *                can be maximally stored into the @colors array;
+ *                on output, how many colors were actually stored.
+ * @colors: (array length=color_count) (out) (optional):
+ *                an array of #hb_color_t records. After calling
+ *                this function, @colors will be filled with
+ *                the palette colors. If @colors is NULL, the function
+ *                will just return the number of total colors
+ *                without storing any actual colors; this can be used
+ *                for allocating a buffer of suitable size before calling
+ *                hb_ot_color_palette_get_colors() a second time.
+ *
+ * Retrieves the colors in a color palette.
+ *
+ * Returns: the total number of colors in the palette.
+ *
+ * Since: 2.1.0
+ */
+unsigned int
+hb_ot_color_palette_get_colors (hb_face_t     *face,
+                                unsigned int   palette_index,
+                                unsigned int   start_offset,
+                                unsigned int  *colors_count  /* IN/OUT.  May be NULL. */,
+                                hb_color_t    *colors        /* OUT.     May be NULL. */)
+{
+  return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors);
+}
+
+
+/*
+ * COLR
+ */
+
+/**
+ * hb_ot_color_has_layers:
+ * @face: a font face.
+ *
+ * Returns: whether COLR table is available.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_layers (hb_face_t *face)
+{
+  return face->table.COLR->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_get_layers:
+ * @face:         a font face.
+ * @glyph:        a layered color glyph id.
+ * @start_offset: starting offset of layers.
+ * @count:  (inout) (optional): gets number of layers available to be written on buffer
+ *                              and returns number of written layers.
+ * @layers: (array length=count) (out) (optional): layers buffer to buffer.
+ *
+ * Returns: Total number of layers a layered color glyph have.
+ *
+ * Since: 2.1.0
+ */
+unsigned int
+hb_ot_color_glyph_get_layers (hb_face_t           *face,
+                              hb_codepoint_t       glyph,
+                              unsigned int         start_offset,
+                              unsigned int        *count, /* IN/OUT.  May be NULL. */
+                              hb_ot_color_layer_t *layers /* OUT.     May be NULL. */)
+{
+  return face->table.COLR->get_glyph_layers (glyph, start_offset, count, layers);
+}
+
+
+/*
+ * SVG
+ */
+
+/**
+ * hb_ot_color_has_svg:
+ * @face: a font face.
+ *
+ * Check whether @face has SVG glyph images.
+ *
+ * Returns true if available, false otherwise.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_svg (hb_face_t *face)
+{
+  return face->table.SVG->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_reference_svg:
+ * @face:  a font face.
+ * @glyph: a svg glyph index.
+ *
+ * Get SVG document for a glyph. The blob may be either plain text or gzip-encoded.
+ *
+ * Returns: (transfer full): respective svg blob of the glyph, if available.
+ *
+ * Since: 2.1.0
+ */
+hb_blob_t *
+hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
+{
+  return face->table.SVG->reference_blob_for_glyph (glyph);
+}
+
+
+/*
+ * PNG: CBDT or sbix
+ */
+
+/**
+ * hb_ot_color_has_png:
+ * @face: a font face.
+ *
+ * Check whether @face has PNG glyph images (either CBDT or sbix tables).
+ *
+ * Returns true if available, false otherwise.
+ *
+ * Since: 2.1.0
+ */
+hb_bool_t
+hb_ot_color_has_png (hb_face_t *face)
+{
+  return face->table.CBDT->has_data () || face->table.sbix->has_data ();
+}
+
+/**
+ * hb_ot_color_glyph_reference_png:
+ * @font:  a font object, not face. upem should be set on
+ *         that font object if one wants to get optimal png blob, otherwise
+ *         return the biggest one
+ * @glyph: a glyph index.
+ *
+ * Get PNG image for a glyph.
+ *
+ * Returns: (transfer full): respective PNG blob of the glyph, if available.
+ *
+ * Since: 2.1.0
+ */
+hb_blob_t *
+hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t  glyph)
+{
+  hb_blob_t *blob = hb_blob_get_empty ();
+
+  if (font->face->table.sbix->has_data ())
+    blob = font->face->table.sbix->reference_png (font, glyph, nullptr, nullptr, nullptr);
+
+  if (!blob->length && font->face->table.CBDT->has_data ())
+    blob = font->face->table.CBDT->reference_png (font, glyph);
+
+  return blob;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color.h	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2016  Google, Inc.
+ * Copyright © 2018  Khaled Hosny
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Sascha Brawer, Behdad Esfahbod
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_COLOR_H
+#define HB_OT_COLOR_H
+
+#include "hb.h"
+#include "hb-ot-name.h"
+
+HB_BEGIN_DECLS
+
+
+/*
+ * Color palettes.
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_palettes (hb_face_t *face);
+
+HB_EXTERN unsigned int
+hb_ot_color_palette_get_count (hb_face_t *face);
+
+HB_EXTERN hb_ot_name_id_t
+hb_ot_color_palette_get_name_id (hb_face_t *face,
+                                 unsigned int palette_index);
+
+HB_EXTERN hb_ot_name_id_t
+hb_ot_color_palette_color_get_name_id (hb_face_t *face,
+                                       unsigned int color_index);
+
+/**
+ * hb_ot_color_palette_flags_t:
+ * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special
+ *   to note about a color palette.
+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: flag indicating that the color
+ *   palette is appropriate to use when displaying the font on a light background such as white.
+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: flag indicating that the color
+ *   palette is appropriate to use when displaying the font on a dark background such as black.
+ *
+ * Since: 2.1.0
+ */
+typedef enum { /*< flags >*/
+  HB_OT_COLOR_PALETTE_FLAG_DEFAULT                      = 0x00000000u,
+  HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND = 0x00000001u,
+  HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND  = 0x00000002u
+} hb_ot_color_palette_flags_t;
+
+HB_EXTERN hb_ot_color_palette_flags_t
+hb_ot_color_palette_get_flags (hb_face_t *face,
+                               unsigned int palette_index);
+
+HB_EXTERN unsigned int
+hb_ot_color_palette_get_colors (hb_face_t    *face,
+                                unsigned int  palette_index,
+                                unsigned int  start_offset,
+                                unsigned int *color_count,  /* IN/OUT.  May be NULL. */
+                                hb_color_t   *colors        /* OUT.     May be NULL. */);
+
+
+/*
+ * Color layers.
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_layers (hb_face_t *face);
+
+/**
+ * hb_ot_color_layer_t:
+ *
+ * Pairs of glyph and color index.
+ *
+ * Since: 2.1.0
+ **/
+typedef struct hb_ot_color_layer_t
+{
+  hb_codepoint_t glyph;
+  unsigned int   color_index;
+} hb_ot_color_layer_t;
+
+HB_EXTERN unsigned int
+hb_ot_color_glyph_get_layers (hb_face_t           *face,
+                              hb_codepoint_t       glyph,
+                              unsigned int         start_offset,
+                              unsigned int        *count, /* IN/OUT.  May be NULL. */
+                              hb_ot_color_layer_t *layers /* OUT.     May be NULL. */);
+
+/*
+ * SVG
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_svg (hb_face_t *face);
+
+HB_EXTERN hb_blob_t *
+hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph);
+
+/*
+ * PNG: CBDT or sbix
+ */
+
+HB_EXTERN hb_bool_t
+hb_ot_color_has_png (hb_face_t *face);
+
+HB_EXTERN hb_blob_t *
+hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t glyph);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_COLOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-deprecated.h	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_DEPRECATED_H
+#define HB_OT_DEPRECATED_H
+
+#include "hb.h"
+#include "hb-ot-name.h"
+
+
+HB_BEGIN_DECLS
+
+#ifndef HB_DISABLE_DEPRECATED
+
+
+/* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
+hb_ot_layout_table_choose_script (hb_face_t      *face,
+                                  hb_tag_t        table_tag,
+                                  const hb_tag_t *script_tags,
+                                  unsigned int   *script_index,
+                                  hb_tag_t       *chosen_script);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_script_select_language) hb_bool_t
+hb_ot_layout_script_find_language (hb_face_t    *face,
+                                   hb_tag_t      table_tag,
+                                   unsigned int  script_index,
+                                   hb_tag_t      language_tag,
+                                   unsigned int *language_index);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) void
+hb_ot_tags_from_script (hb_script_t  script,
+                        hb_tag_t    *script_tag_1,
+                        hb_tag_t    *script_tag_2);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_tags_from_script_and_language) hb_tag_t
+hb_ot_tag_from_language (hb_language_t language);
+
+
+/**
+ * HB_OT_VAR_NO_AXIS_INDEX:
+ *
+ * Since: 1.4.2
+ * Deprecated: 2.2.0
+ */
+#define HB_OT_VAR_NO_AXIS_INDEX         0xFFFFFFFFu
+
+/**
+ * hb_ot_var_axis_t:
+ *
+ * Since: 1.4.2
+ * Deprecated: 2.2.0
+ */
+typedef struct hb_ot_var_axis_t
+{
+  hb_tag_t tag;
+  hb_ot_name_id_t name_id;
+  float min_value;
+  float default_value;
+  float max_value;
+} hb_ot_var_axis_t;
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_get_axis_infos) unsigned int
+hb_ot_var_get_axes (hb_face_t        *face,
+                    unsigned int      start_offset,
+                    unsigned int     *axes_count /* IN/OUT */,
+                    hb_ot_var_axis_t *axes_array /* OUT */);
+
+HB_EXTERN HB_DEPRECATED_FOR (hb_ot_var_find_axis_info) hb_bool_t
+hb_ot_var_find_axis (hb_face_t        *face,
+                     hb_tag_t          axis_tag,
+                     unsigned int     *axis_index,
+                     hb_ot_var_axis_t *axis_info);
+
+
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_OT_DEPRECATED_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-face.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-ot-face.hh"
+
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-ot-hmtx-table.hh"
+#include "hb-ot-kern-table.hh"
+#include "hb-ot-name-table.hh"
+#include "hb-ot-post-table.hh"
+#include "hb-ot-color-cbdt-table.hh"
+#include "hb-ot-color-sbix-table.hh"
+#include "hb-ot-color-svg-table.hh"
+#include "hb-ot-layout-gdef-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gpos-table.hh"
+
+
+void hb_ot_face_t::init0 (hb_face_t *face)
+{
+  this->face = face;
+#define HB_OT_TABLE(Namespace, Type) Type.init0 ();
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+}
+void hb_ot_face_t::fini ()
+{
+#define HB_OT_TABLE(Namespace, Type) Type.fini ();
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-face.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2012,2013  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_FACE_HH
+#define HB_OT_FACE_HH
+
+#include "hb.hh"
+
+#include "hb-machinery.hh"
+
+
+/*
+ * hb_ot_face_t
+ */
+
+#define HB_OT_TABLES \
+    /* OpenType fundamentals. */ \
+    HB_OT_TABLE(OT, head) \
+    HB_OT_ACCELERATOR(OT, cmap) \
+    HB_OT_ACCELERATOR(OT, hmtx) \
+    HB_OT_ACCELERATOR(OT, vmtx) \
+    HB_OT_ACCELERATOR(OT, post) \
+    HB_OT_TABLE(OT, kern) \
+    HB_OT_ACCELERATOR(OT, glyf) \
+    HB_OT_ACCELERATOR(OT, cff1) \
+    HB_OT_ACCELERATOR(OT, cff2) \
+    HB_OT_TABLE(OT, VORG) \
+    HB_OT_ACCELERATOR(OT, name) \
+    HB_OT_TABLE(OT, OS2) \
+    HB_OT_TABLE(OT, STAT) \
+    /* OpenType shaping. */ \
+    HB_OT_ACCELERATOR(OT, GDEF) \
+    HB_OT_ACCELERATOR(OT, GSUB) \
+    HB_OT_ACCELERATOR(OT, GPOS) \
+    HB_OT_TABLE(OT, BASE) \
+    HB_OT_TABLE(OT, JSTF) \
+    /* AAT shaping. */ \
+    HB_OT_TABLE(AAT, mort) \
+    HB_OT_TABLE(AAT, morx) \
+    HB_OT_TABLE(AAT, kerx) \
+    HB_OT_TABLE(AAT, ankr) \
+    HB_OT_TABLE(AAT, trak) \
+    HB_OT_TABLE(AAT, lcar) \
+    HB_OT_TABLE(AAT, ltag) \
+    HB_OT_TABLE(AAT, feat) \
+    /* OpenType variations. */ \
+    HB_OT_TABLE(OT, fvar) \
+    HB_OT_TABLE(OT, avar) \
+    HB_OT_TABLE(OT, MVAR) \
+    /* OpenType math. */ \
+    HB_OT_TABLE(OT, MATH) \
+    /* OpenType color fonts. */ \
+    HB_OT_TABLE(OT, COLR) \
+    HB_OT_TABLE(OT, CPAL) \
+    HB_OT_ACCELERATOR(OT, CBDT) \
+    HB_OT_ACCELERATOR(OT, sbix) \
+    HB_OT_ACCELERATOR(OT, SVG) \
+    /* */
+
+/* Declare tables. */
+#define HB_OT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type##_accelerator_t)
+HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+
+struct hb_ot_face_t
+{
+  HB_INTERNAL void init0 (hb_face_t *face);
+  HB_INTERNAL void fini ();
+
+#define HB_OT_TABLE_ORDER(Namespace, Type) \
+    HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
+  enum order_t
+  {
+    ORDER_ZERO,
+#define HB_OT_TABLE(Namespace, Type) HB_OT_TABLE_ORDER (Namespace, Type),
+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+    HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+  };
+
+  hb_face_t *face; /* MUST be JUST before the lazy loaders. */
+#define HB_OT_TABLE(Namespace, Type) \
+  hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+#define HB_OT_ACCELERATOR(Namespace, Type) \
+  hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+  HB_OT_TABLES
+#undef HB_OT_ACCELERATOR
+#undef HB_OT_TABLE
+};
+
+
+#endif /* HB_OT_FACE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-font.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,67 +24,38 @@
  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb-ot.h"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+#include "hb-ot-face.hh"
 
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
 #include "hb-ot-hmtx-table.hh"
 #include "hb-ot-kern-table.hh"
+#include "hb-ot-os2-table.hh"
 #include "hb-ot-post-table.hh"
-
+#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-vorg-table.hh"
 #include "hb-ot-color-cbdt-table.hh"
-
-
-struct hb_ot_font_t
-{
-  OT::cmap::accelerator_t cmap;
-  OT::hmtx::accelerator_t h_metrics;
-  OT::vmtx::accelerator_t v_metrics;
-  OT::hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
-  OT::hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt;
-  OT::hb_lazy_loader_t<OT::post::accelerator_t> post;
-  OT::hb_lazy_loader_t<OT::kern::accelerator_t> kern;
-};
+#include "hb-ot-color-sbix-table.hh"
 
 
-static hb_ot_font_t *
-_hb_ot_font_create (hb_face_t *face)
-{
-  hb_ot_font_t *ot_font = (hb_ot_font_t *) calloc (1, sizeof (hb_ot_font_t));
-
-  if (unlikely (!ot_font))
-    return nullptr;
-
-  ot_font->cmap.init (face);
-  ot_font->h_metrics.init (face);
-  ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
-  ot_font->glyf.init (face);
-  ot_font->cbdt.init (face);
-  ot_font->post.init (face);
-  ot_font->kern.init (face);
-
-  return ot_font;
-}
-
-static void
-_hb_ot_font_destroy (void *data)
-{
-  hb_ot_font_t *ot_font = (hb_ot_font_t *) data;
-
-  ot_font->cmap.fini ();
-  ot_font->h_metrics.fini ();
-  ot_font->v_metrics.fini ();
-  ot_font->glyf.fini ();
-  ot_font->cbdt.fini ();
-  ot_font->post.fini ();
-  ot_font->kern.fini ();
-
-  free (ot_font);
-}
+/**
+ * SECTION:hb-ot-font
+ * @title: hb-ot-font
+ * @short_description: OpenType font implementation
+ * @include: hb-ot.h
+ *
+ * Functions for using OpenType fonts with hb_shape().  Not that fonts returned
+ * by hb_font_create() default to using these functions, so most clients would
+ * never need to call these functions directly.
+ **/
 
 
 static hb_bool_t
@@ -93,10 +64,25 @@
                          hb_codepoint_t unicode,
                          hb_codepoint_t *glyph,
                          void *user_data HB_UNUSED)
-
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_nominal_glyph (unicode, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_nominal_glyph (unicode, glyph);
+}
+
+static unsigned int
+hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
+                          void *font_data,
+                          unsigned int count,
+                          const hb_codepoint_t *first_unicode,
+                          unsigned int unicode_stride,
+                          hb_codepoint_t *first_glyph,
+                          unsigned int glyph_stride,
+                          void *user_data HB_UNUSED)
+{
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_nominal_glyphs (count,
+                                            first_unicode, unicode_stride,
+                                            first_glyph, glyph_stride);
 }
 
 static hb_bool_t
@@ -107,39 +93,83 @@
                            hb_codepoint_t *glyph,
                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->cmap.get_variation_glyph (unicode, variation_selector, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
 }
 
-static hb_position_t
-hb_ot_get_glyph_h_advance (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t glyph,
-                           void *user_data HB_UNUSED)
+static void
+hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
+                            unsigned count,
+                            const hb_codepoint_t *first_glyph,
+                            unsigned glyph_stride,
+                            hb_position_t *first_advance,
+                            unsigned advance_stride,
+                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->h_metrics.get_advance (glyph, font));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
+
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font));
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
-static hb_position_t
-hb_ot_get_glyph_v_advance (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t glyph,
-                           void *user_data HB_UNUSED)
+static void
+hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
+                            unsigned count,
+                            const hb_codepoint_t *first_glyph,
+                            unsigned glyph_stride,
+                            hb_position_t *first_advance,
+                            unsigned advance_stride,
+                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_y (-(int) ot_font->v_metrics.get_advance (glyph, font));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+
+  for (unsigned int i = 0; i < count; i++)
+  {
+    *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
+    first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+    first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+  }
 }
 
-static hb_position_t
-hb_ot_get_glyph_h_kerning (hb_font_t *font,
-                           void *font_data,
-                           hb_codepoint_t left_glyph,
-                           hb_codepoint_t right_glyph,
-                           void *user_data HB_UNUSED)
+static hb_bool_t
+hb_ot_get_glyph_v_origin (hb_font_t *font,
+                          void *font_data,
+                          hb_codepoint_t glyph,
+                          hb_position_t *x,
+                          hb_position_t *y,
+                          void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph));
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+
+  *x = font->get_glyph_h_advance (glyph) / 2;
+
+  const OT::VORG &VORG = *ot_face->VORG;
+  if (VORG.has_data ())
+  {
+    *y = font->em_scale_y (VORG.get_y_origin (glyph));
+    return true;
+  }
+
+  hb_glyph_extents_t extents = {0};
+  if (ot_face->glyf->get_extents (glyph, &extents))
+  {
+    const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+    hb_position_t tsb = vmtx.get_side_bearing (glyph);
+    *y = font->em_scale_y (extents.y_bearing + tsb);
+    return true;
+  }
+
+  hb_font_extents_t font_extents;
+  font->get_h_extents_with_fallback (&font_extents);
+  *y = font_extents.ascender;
+
+  return true;
 }
 
 static hb_bool_t
@@ -149,10 +179,16 @@
                          hb_glyph_extents_t *extents,
                          void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  bool ret = ot_font->glyf->get_extents (glyph, extents);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  bool ret = ot_face->sbix->get_extents (font, glyph, extents);
+  if (!ret)
+    ret = ot_face->glyf->get_extents (glyph, extents);
   if (!ret)
-    ret = ot_font->cbdt->get_extents (glyph, extents);
+    ret = ot_face->cff1->get_extents (glyph, extents);
+  if (!ret)
+    ret = ot_face->cff2->get_extents (font, glyph, extents);
+  if (!ret)
+    ret = ot_face->CBDT->get_extents (font, glyph, extents);
   // TODO Hook up side-bearings variations.
   extents->x_bearing = font->em_scale_x (extents->x_bearing);
   extents->y_bearing = font->em_scale_y (extents->y_bearing);
@@ -168,8 +204,8 @@
                       char *name, unsigned int size,
                       void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->post->get_glyph_name (glyph, name, size);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->post->get_glyph_name (glyph, name, size);
 }
 
 static hb_bool_t
@@ -179,8 +215,8 @@
                            hb_codepoint_t *glyph,
                            void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  return ot_font->post->get_glyph_from_name (name, len, glyph);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  return ot_face->post->get_glyph_from_name (name, len, glyph);
 }
 
 static hb_bool_t
@@ -189,12 +225,13 @@
                           hb_font_extents_t *metrics,
                           void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  metrics->ascender = font->em_scale_y (ot_font->h_metrics.ascender);
-  metrics->descender = font->em_scale_y (ot_font->h_metrics.descender);
-  metrics->line_gap = font->em_scale_y (ot_font->h_metrics.line_gap);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
+  metrics->ascender = font->em_scale_y (hmtx.ascender);
+  metrics->descender = font->em_scale_y (hmtx.descender);
+  metrics->line_gap = font->em_scale_y (hmtx.line_gap);
   // TODO Hook up variations.
-  return ot_font->h_metrics.has_font_extents;
+  return hmtx.has_font_extents;
 }
 
 static hb_bool_t
@@ -203,49 +240,34 @@
                           hb_font_extents_t *metrics,
                           void *user_data HB_UNUSED)
 {
-  const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
-  metrics->ascender = font->em_scale_x (ot_font->v_metrics.ascender);
-  metrics->descender = font->em_scale_x (ot_font->v_metrics.descender);
-  metrics->line_gap = font->em_scale_x (ot_font->v_metrics.line_gap);
+  const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+  const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+  metrics->ascender = font->em_scale_x (vmtx.ascender);
+  metrics->descender = font->em_scale_x (vmtx.descender);
+  metrics->line_gap = font->em_scale_x (vmtx.line_gap);
   // TODO Hook up variations.
-  return ot_font->v_metrics.has_font_extents;
+  return vmtx.has_font_extents;
 }
 
-static hb_font_funcs_t *static_ot_funcs = nullptr;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_ot_funcs (void)
-{
-retry:
-  hb_font_funcs_t *ot_funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, ot_funcs, nullptr))
-    goto retry;
-
-  hb_font_funcs_destroy (ot_funcs);
-}
+#if HB_USE_ATEXIT
+static void free_static_ot_funcs ();
 #endif
 
-static hb_font_funcs_t *
-_hb_ot_get_font_funcs (void)
+static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
 {
-retry:
-  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
-
-  if (unlikely (!funcs))
+  static hb_font_funcs_t *create ()
   {
-    funcs = hb_font_funcs_create ();
+    hb_font_funcs_t *funcs = hb_font_funcs_create ();
 
     hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
     hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr);
+    hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr);
-    hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr);
+    hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
+    hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr);
-    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, nullptr, nullptr);
+    hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
     //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
@@ -253,17 +275,26 @@
 
     hb_font_funcs_make_immutable (funcs);
 
-    if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, nullptr, funcs)) {
-      hb_font_funcs_destroy (funcs);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_ot_funcs);
+#endif
+
+    return funcs;
+  }
+} static_ot_funcs;
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_ot_funcs ()
+{
+  static_ot_funcs.free_instance ();
+}
 #endif
-  };
 
-  return funcs;
+static hb_font_funcs_t *
+_hb_ot_get_font_funcs ()
+{
+  return static_ot_funcs.get_unconst ();
 }
 
 
@@ -275,12 +306,8 @@
 void
 hb_ot_font_set_funcs (hb_font_t *font)
 {
-  hb_ot_font_t *ot_font = _hb_ot_font_create (font->face);
-  if (unlikely (!ot_font))
-    return;
-
   hb_font_set_funcs (font,
                      _hb_ot_get_font_funcs (),
-                     ot_font,
-                     _hb_ot_font_destroy);
+                     &font->face->table,
+                     nullptr);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-gasp-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_OT_GASP_TABLE_HH
+#define HB_OT_GASP_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-var-hvar-table.hh"
+
+/*
+ * gasp -- Grid-fitting and Scan-conversion Procedure
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gasp
+ */
+#define HB_OT_TAG_gasp HB_TAG('g','a','s','p')
+
+
+namespace OT {
+
+struct GaspRange
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT16      rangeMaxPPEM;   /* Upper limit of range, in PPEM */
+  HBUINT16      rangeGaspBehavior;
+                                /* Flags describing desired rasterizer behavior. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct gasp
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_gasp;
+
+  const GaspRange &get_gasp_range (unsigned int i) const
+  { return gaspRanges[i]; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  gaspRanges.sanitize (c));
+  }
+
+  protected:
+  HBUINT16      version;        /* Version number (set to 1) */
+  ArrayOf<GaspRange>
+                gaspRanges;     /* Number of records to follow
+                                 * Sorted by ppem */
+  public:
+  DEFINE_SIZE_ARRAY (4, gaspRanges);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_GASP_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-glyf-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-glyf-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,11 +27,9 @@
 #ifndef HB_OT_GLYF_TABLE_HH
 #define HB_OT_GLYF_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-subset-glyf.hh"
-#include "hb-subset-plan.hh"
-#include "hb-subset-private.hh"
 
 namespace OT {
 
@@ -47,17 +45,20 @@
 {
   friend struct glyf;
 
-  static const hb_tag_t tableTag = HB_OT_TAG_loca;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     return_trace (true);
   }
 
   protected:
-  HBUINT8               dataZ[VAR];             /* Location data. */
-  DEFINE_SIZE_ARRAY (0, dataZ);
+  UnsizedArrayOf<HBUINT8>       dataZ;          /* Location data. */
+  public:
+  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+                        * check the size externally, allow Null() object of it by
+                        * defining it MIN() instead. */
 };
 
 
@@ -70,9 +71,9 @@
 
 struct glyf
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_glyf;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
@@ -80,7 +81,7 @@
     return_trace (true);
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     hb_blob_t *glyf_prime = nullptr;
     hb_blob_t *loca_prime = nullptr;
@@ -103,14 +104,14 @@
   static bool
   _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
   {
-    hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_head));
+    hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
     hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
     hb_blob_destroy (head_blob);
 
     if (unlikely (!head_prime_blob))
       return false;
 
-    OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
+    head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
     head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
     bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
 
@@ -150,28 +151,23 @@
     };
 
     HBUINT16 flags;
-    HBUINT16 glyphIndex;
+    GlyphID  glyphIndex;
 
-    inline unsigned int get_size (void) const
+    unsigned int get_size () const
     {
       unsigned int size = min_size;
-      if (flags & ARG_1_AND_2_ARE_WORDS) {
-        // arg1 and 2 are int16
-        size += 4;
-      } else {
-        // arg1 and 2 are int8
-        size += 2;
-      }
-      if (flags & WE_HAVE_A_SCALE) {
-        // One x 16 bit (scale)
-        size += 2;
-      } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
-        // Two x 16 bit (xscale, yscale)
-        size += 4;
-      } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
-        // Four x 16 bit (xscale, scale01, scale10, yscale)
-        size += 8;
-      }
+      // arg1 and 2 are int16
+      if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
+      // arg1 and 2 are int8
+      else size += 2;
+
+      // One x 16 bit (scale)
+      if (flags & WE_HAVE_A_SCALE) size += 2;
+      // Two x 16 bit (xscale, yscale)
+      else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
+      // Four x 16 bit (xscale, scale01, scale10, yscale)
+      else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
+
       return size;
     }
 
@@ -181,7 +177,7 @@
       const char *glyph_end;
       const CompositeGlyphHeader *current;
 
-      inline bool move_to_next ()
+      bool move_to_next ()
       {
         if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS)
         {
@@ -195,17 +191,17 @@
         return false;
       }
 
-      inline bool in_range (const CompositeGlyphHeader *composite) const
+      bool in_range (const CompositeGlyphHeader *composite) const
       {
         return (const char *) composite >= glyph_start
           && ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
-          && ((const char *) composite + composite->get_size()) <= glyph_end;
+          && ((const char *) composite + composite->get_size ()) <= glyph_end;
       }
     };
 
-    static inline bool get_iterator (const char * glyph_data,
-                                     unsigned int length,
-                                     CompositeGlyphHeader::Iterator *iterator /* OUT */)
+    static bool get_iterator (const char * glyph_data,
+                              unsigned int length,
+                              CompositeGlyphHeader::Iterator *iterator /* OUT */)
     {
       if (length < GlyphHeader::static_size)
         return false; /* Empty glyph; zero extents. */
@@ -232,34 +228,26 @@
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
       memset (this, 0, sizeof (accelerator_t));
 
-      hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
-      const head *head_table = head_blob->as<head> ();
-      if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
-      {
-        /* head table is not present, or in an unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
-        hb_blob_destroy (head_blob);
+      const OT::head &head = *face->table.head;
+      if (head.indexToLocFormat > 1 || head.glyphDataFormat != 0)
+        /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
         return;
-      }
-      short_offset = 0 == head_table->indexToLocFormat;
-      hb_blob_destroy (head_blob);
+      short_offset = 0 == head.indexToLocFormat;
 
-      loca_blob = Sanitizer<loca>().sanitize (face->reference_table (HB_OT_TAG_loca));
-      loca_table = loca_blob->as<loca> ();
-      glyf_blob = Sanitizer<glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
-      glyf_table = glyf_blob->as<glyf> ();
+      loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
+      glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
 
-      num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
-      glyf_len = hb_blob_get_length (glyf_blob);
+      num_glyphs = MAX (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
     }
 
-    inline void fini (void)
+    void fini ()
     {
-      hb_blob_destroy (loca_blob);
-      hb_blob_destroy (glyf_blob);
+      loca_table.destroy ();
+      glyf_table.destroy ();
     }
 
     /*
@@ -267,35 +255,37 @@
      * If true is returned a pointer to the composite glyph will be written into
      * composite.
      */
-    inline bool get_composite (hb_codepoint_t glyph,
-                               CompositeGlyphHeader::Iterator *composite /* OUT */) const
+    bool get_composite (hb_codepoint_t glyph,
+                        CompositeGlyphHeader::Iterator *composite /* OUT */) const
     {
-      if (this->glyf_table == &Null(glyf) || !num_glyphs)
+      if (unlikely (!num_glyphs))
         return false;
 
       unsigned int start_offset, end_offset;
       if (!get_offsets (glyph, &start_offset, &end_offset))
         return false; /* glyph not found */
 
-      return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset,
+      return CompositeGlyphHeader::get_iterator ((const char *) this->glyf_table + start_offset,
                                                  end_offset - start_offset,
                                                  composite);
     }
 
     enum simple_glyph_flag_t {
+      FLAG_ON_CURVE = 0x01,
       FLAG_X_SHORT = 0x02,
       FLAG_Y_SHORT = 0x04,
       FLAG_REPEAT = 0x08,
       FLAG_X_SAME = 0x10,
-      FLAG_Y_SAME = 0x20
+      FLAG_Y_SAME = 0x20,
+      FLAG_RESERVED1 = 0x40,
+      FLAG_RESERVED2 = 0x80
     };
 
     /* based on FontTools _g_l_y_f.py::trim */
-    inline bool remove_padding(unsigned int start_offset,
-                               unsigned int *end_offset) const
+    bool remove_padding (unsigned int start_offset,
+                                unsigned int *end_offset) const
     {
-      if (*end_offset - start_offset < GlyphHeader::static_size)
-        return true;
+      if (*end_offset - start_offset < GlyphHeader::static_size) return true;
 
       const char *glyph = ((const char *) glyf_table) + start_offset;
       const char * const glyph_end = glyph + (*end_offset - start_offset);
@@ -312,8 +302,8 @@
         glyph += GlyphHeader::static_size + 2 * num_contours;
 
         if (unlikely (glyph + 2 >= glyph_end)) return false;
-        uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16>(glyph - 2, 0) + 1;
-        uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16>(glyph, 0);
+        uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
+        uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16> (glyph, 0);
 
         glyph += 2 + nInstructions;
         if (unlikely (glyph + 2 >= glyph_end)) return false;
@@ -339,15 +329,11 @@
 
           unsigned int xBytes, yBytes;
           xBytes = yBytes = 0;
-          if (flag & FLAG_X_SHORT)
-            xBytes = 1;
-          else if ((flag & FLAG_X_SAME) == 0)
-            xBytes = 2;
+          if (flag & FLAG_X_SHORT) xBytes = 1;
+          else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
 
-          if (flag & FLAG_Y_SHORT)
-            yBytes = 1;
-          else if ((flag & FLAG_Y_SAME) == 0)
-            yBytes = 2;
+          if (flag & FLAG_Y_SHORT) yBytes = 1;
+          else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
 
           coordBytes += (xBytes + yBytes) * repeat;
           coordsWithFlags += repeat;
@@ -368,37 +354,37 @@
       return true;
     }
 
-    inline bool get_offsets (hb_codepoint_t  glyph,
-                             unsigned int   *start_offset /* OUT */,
-                             unsigned int   *end_offset   /* OUT */) const
+    bool get_offsets (hb_codepoint_t  glyph,
+                      unsigned int   *start_offset /* OUT */,
+                      unsigned int   *end_offset   /* OUT */) const
     {
       if (unlikely (glyph >= num_glyphs))
         return false;
 
       if (short_offset)
       {
-        const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ;
+        const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
         *start_offset = 2 * offsets[glyph];
         *end_offset   = 2 * offsets[glyph + 1];
       }
       else
       {
-        const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ;
+        const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
 
         *start_offset = offsets[glyph];
         *end_offset   = offsets[glyph + 1];
       }
 
-      if (*start_offset > *end_offset || *end_offset > glyf_len)
+      if (*start_offset > *end_offset || *end_offset > glyf_table.get_length ())
         return false;
 
       return true;
     }
 
-    inline bool get_instruction_offsets(unsigned int start_offset,
-                                        unsigned int end_offset,
-                                        unsigned int *instruction_start /* OUT */,
-                                        unsigned int *instruction_end /* OUT */) const
+    bool get_instruction_offsets (unsigned int start_offset,
+                                  unsigned int end_offset,
+                                  unsigned int *instruction_start /* OUT */,
+                                  unsigned int *instruction_end /* OUT */) const
     {
       if (end_offset - start_offset < GlyphHeader::static_size)
       {
@@ -417,10 +403,10 @@
         const CompositeGlyphHeader *last;
         do {
           last = composite_it.current;
-        } while (composite_it.move_to_next());
+        } while (composite_it.move_to_next ());
 
-        if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
-          *instruction_start = ((char *) last - (char *) glyf_table->dataZ) + last->get_size();
+        if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
+          *instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size ();
         else
           *instruction_start = end_offset;
         *instruction_end = end_offset;
@@ -454,8 +440,7 @@
       return true;
     }
 
-    inline bool get_extents (hb_codepoint_t glyph,
-                             hb_glyph_extents_t *extents) const
+    bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
     {
       unsigned int start_offset, end_offset;
       if (!get_offsets (glyph, &start_offset, &end_offset))
@@ -477,18 +462,19 @@
     private:
     bool short_offset;
     unsigned int num_glyphs;
-    const loca *loca_table;
-    const glyf *glyf_table;
-    hb_blob_t *loca_blob;
-    hb_blob_t *glyf_blob;
-    unsigned int glyf_len;
+    hb_blob_ptr_t<loca> loca_table;
+    hb_blob_ptr_t<glyf> glyf_table;
   };
 
   protected:
-  HBUINT8               dataZ[VAR];             /* Glyphs data. */
+  UnsizedArrayOf<HBUINT8>       dataZ;          /* Glyphs data. */
+  public:
+  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+                        * check the size externally, allow Null() object of it by
+                        * defining it MIN() instead. */
+};
 
-  DEFINE_SIZE_ARRAY (0, dataZ);
-};
+struct glyf_accelerator_t : glyf::accelerator_t {};
 
 } /* namespace OT */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hdmx-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,214 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef HB_OT_HDMX_TABLE_HH
+#define HB_OT_HDMX_TABLE_HH
+
+#include "hb-open-type.hh"
+
+/*
+ * hdmx -- Horizontal Device Metrics
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/hdmx
+ */
+#define HB_OT_TAG_hdmx HB_TAG('h','d','m','x')
+
+
+namespace OT {
+
+
+struct DeviceRecord
+{
+  struct SubsetView
+  {
+    const DeviceRecord *source_device_record;
+    unsigned int sizeDeviceRecord;
+    hb_subset_plan_t *subset_plan;
+
+    void init (const DeviceRecord *source_device_record,
+               unsigned int sizeDeviceRecord,
+               hb_subset_plan_t   *subset_plan)
+    {
+      this->source_device_record = source_device_record;
+      this->sizeDeviceRecord = sizeDeviceRecord;
+      this->subset_plan = subset_plan;
+    }
+
+    unsigned int len () const
+    { return this->subset_plan->glyphs.length; }
+
+    const HBUINT8* operator [] (unsigned int i) const
+    {
+      if (unlikely (i >= len ())) return nullptr;
+      hb_codepoint_t gid = this->subset_plan->glyphs [i];
+
+      if (gid >= sizeDeviceRecord - DeviceRecord::min_size)
+        return nullptr;
+      return &(this->source_device_record->widthsZ[gid]);
+    }
+  };
+
+  static unsigned int get_size (unsigned int count)
+  { return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); }
+
+  bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
+  {
+    TRACE_SERIALIZE (this);
+
+    unsigned int size = get_size (subset_view.len ());
+    if (unlikely (!c->allocate_size<DeviceRecord> (size)))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Couldn't allocate enough space for DeviceRecord: %d.",
+                 size);
+      return_trace (false);
+    }
+
+    this->pixelSize.set (subset_view.source_device_record->pixelSize);
+    this->maxWidth.set (subset_view.source_device_record->maxWidth);
+
+    for (unsigned int i = 0; i < subset_view.len (); i++)
+    {
+      const HBUINT8 *width = subset_view[i];
+      if (!width)
+      {
+        DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
+        return_trace (false);
+      }
+      widthsZ[i].set (*width);
+    }
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          c->check_range (this, sizeDeviceRecord)));
+  }
+
+  HBUINT8                       pixelSize;      /* Pixel size for following widths (as ppem). */
+  HBUINT8                       maxWidth;       /* Maximum width. */
+  UnsizedArrayOf<HBUINT8>       widthsZ;        /* Array of widths (numGlyphs is from the 'maxp' table). */
+  public:
+  DEFINE_SIZE_ARRAY (2, widthsZ);
+};
+
+
+struct hdmx
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hdmx;
+
+  unsigned int get_size () const
+  { return min_size + numRecords * sizeDeviceRecord; }
+
+  const DeviceRecord& operator [] (unsigned int i) const
+  {
+    /* XXX Null(DeviceRecord) is NOT safe as it's num-glyphs lengthed.
+     * https://github.com/harfbuzz/harfbuzz/issues/1300 */
+    if (unlikely (i >= numRecords)) return Null (DeviceRecord);
+    return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
+  }
+
+  bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  {
+    TRACE_SERIALIZE (this);
+
+    if (unlikely (!c->extend_min ((*this))))  return_trace (false);
+
+    this->version.set (source_hdmx->version);
+    this->numRecords.set (source_hdmx->numRecords);
+    this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->glyphs.length));
+
+    for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
+    {
+      DeviceRecord::SubsetView subset_view;
+      subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan);
+
+      if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
+  static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
+  {
+    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->glyphs.length);
+  }
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    size_t dest_size = get_subsetted_size (this, plan);
+    hdmx *dest = (hdmx *) malloc (dest_size);
+    if (unlikely (!dest))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size);
+      return false;
+    }
+
+    hb_serialize_context_t c (dest, dest_size);
+    hdmx *hdmx_prime = c.start_serialize<hdmx> ();
+    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan))
+    {
+      free (dest);
+      DEBUG_MSG(SUBSET, nullptr, "Failed to serialize write new hdmx.");
+      return false;
+    }
+    c.end_serialize ();
+
+    hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest,
+                                                 dest_size,
+                                                 HB_MEMORY_MODE_READONLY,
+                                                 dest,
+                                                 free);
+    bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob);
+    hb_blob_destroy (hdmx_prime_blob);
+
+    return result;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  !hb_unsigned_mul_overflows (numRecords, sizeDeviceRecord) &&
+                  sizeDeviceRecord >= DeviceRecord::min_size &&
+                  c->check_range (this, get_size ()));
+  }
+
+  protected:
+  HBUINT16              version;                /* Table version number (0) */
+  HBUINT16              numRecords;             /* Number of device records. */
+  HBUINT32              sizeDeviceRecord;       /* Size of a device record, 32-bit aligned. */
+  DeviceRecord          firstDeviceRecord;      /* Array of device records. */
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_HDMX_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-head-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-head-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,7 +29,7 @@
 #ifndef HB_OT_HEAD_TABLE_HH
 #define HB_OT_HEAD_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * head -- Font Header
@@ -45,16 +45,29 @@
 {
   friend struct OffsetTable;
 
-  static const hb_tag_t tableTag        = HB_OT_TAG_head;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_head;
 
-  inline unsigned int get_upem (void) const
+  unsigned int get_upem () const
   {
     unsigned int upem = unitsPerEm;
     /* If no valid head table found, assume 1000, which matches typical Type1 usage. */
     return 16 <= upem && upem <= 16384 ? upem : 1000;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  enum mac_style_flag_t {
+    BOLD        = 1u<<0,
+    ITALIC      = 1u<<1,
+    UNDERLINE   = 1u<<2,
+    OUTLINE     = 1u<<3,
+    SHADOW      = 1u<<4,
+    CONDENSED   = 1u<<5
+  };
+
+  bool is_bold () const      { return macStyle & BOLD; }
+  bool is_italic () const    { return macStyle & ITALIC; }
+  bool is_condensed () const { return macStyle & CONDENSED; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -141,8 +154,8 @@
                                          * -1: Only strongly right to left;
                                          * -2: Like -1 but also contains neutrals. */
   public:
-  HBINT16       indexToLocFormat;       /* 0 for short offsets, 1 for long. */
-  HBINT16       glyphDataFormat;        /* 0 for current format. */
+  HBUINT16      indexToLocFormat;       /* 0 for short offsets, 1 for long. */
+  HBUINT16      glyphDataFormat;        /* 0 for current format. */
 
   DEFINE_SIZE_STATIC (54);
 };
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hhea-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hhea-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,7 @@
 #ifndef HB_OT_HHEA_TABLE_HH
 #define HB_OT_HHEA_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * hhea -- Horizontal Header
@@ -45,7 +45,7 @@
 template <typename T>
 struct _hea
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && likely (version.major == 1));
@@ -86,10 +86,10 @@
 };
 
 struct hhea : _hea<hhea> {
-  static const hb_tag_t tableTag        = HB_OT_TAG_hhea;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hhea;
 };
 struct vhea : _hea<vhea> {
-  static const hb_tag_t tableTag        = HB_OT_TAG_vhea;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_vhea;
 };
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,11 +27,10 @@
 #ifndef HB_OT_HMTX_TABLE_HH
 #define HB_OT_HMTX_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-hhea-table.hh"
 #include "hb-ot-os2-table.hh"
 #include "hb-ot-var-hvar-table.hh"
-#include "hb-subset-plan.hh"
 
 /*
  * hmtx -- Horizontal Metrics
@@ -49,7 +48,7 @@
 struct LongMetric
 {
   UFWORD        advance; /* Advance width/height. */
-  FWORD         lsb; /* Leading (left/top) side bearing. */
+  FWORD         sb; /* Leading (left/top) side bearing. */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -57,7 +56,7 @@
 template <typename T, typename H>
 struct hmtxvmtx
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
   {
     TRACE_SANITIZE (this);
     /* We don't check for anything specific here.  The users of the
@@ -66,11 +65,11 @@
   }
 
 
-  inline bool subset_update_header (hb_subset_plan_t *plan,
+  bool subset_update_header (hb_subset_plan_t *plan,
                                     unsigned int num_hmetrics) const
   {
-    hb_blob_t *src_blob = OT::Sanitizer<H> ().sanitize (plan->source->reference_table (H::tableTag));
-    hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob);
+    hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
+    hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
     hb_blob_destroy (src_blob);
 
     if (unlikely (!dest_blob)) {
@@ -87,7 +86,7 @@
     return result;
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     typename T::accelerator_t _mtx;
     _mtx.init (plan->source);
@@ -95,33 +94,33 @@
     /* All the trailing glyphs with the same advance can use one LongMetric
      * and just keep LSB */
     hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
-    unsigned int num_advances = gids.len;
+    unsigned int num_advances = gids.length;
     unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
-    while (num_advances > 1
-        && last_advance == _mtx.get_advance (gids[num_advances - 2]))
+    while (num_advances > 1 &&
+           last_advance == _mtx.get_advance (gids[num_advances - 2]))
     {
       num_advances--;
     }
 
     /* alloc the new table */
     size_t dest_sz = num_advances * 4
-                  + (gids.len - num_advances) * 2;
+                  + (gids.length - num_advances) * 2;
     void *dest = (void *) malloc (dest_sz);
     if (unlikely (!dest))
     {
       return false;
     }
     DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
-    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.len - num_advances, (unsigned int) dest_sz);
+    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.length - num_advances, (unsigned int) dest_sz);
 
-    const char *source_table = hb_blob_get_data (_mtx.blob, nullptr);
+    const char *source_table = hb_blob_get_data (_mtx.table.get_blob (), nullptr);
     // Copy everything over
     LongMetric * old_metrics = (LongMetric *) source_table;
     FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
     char * dest_pos = (char *) dest;
 
     bool failed = false;
-    for (unsigned int i = 0; i < gids.len; i++)
+    for (unsigned int i = 0; i < gids.length; i++)
     {
       /* the last metric or the one for gids[i] */
       LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
@@ -135,8 +134,8 @@
         }
         else
         {
-          /* dest just lsb */
-          *((FWORD *) dest_pos) = src_metric->lsb;
+          /* dest just sb */
+          *((FWORD *) dest_pos) = src_metric->sb;
         }
       }
       else
@@ -148,18 +147,18 @@
           failed = true;
           break;
         }
-        FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
+        FWORD src_sb = *(lsbs + gids[i] - _mtx.num_advances);
         if (i < num_advances)
         {
           /* dest needs a full LongMetric */
           LongMetric *metric = (LongMetric *)dest_pos;
           metric->advance = src_metric->advance;
-          metric->lsb = src_lsb;
+          metric->sb = src_sb;
         }
         else
         {
-          /* dest just needs an lsb */
-          *((FWORD *) dest_pos) = src_lsb;
+          /* dest just needs an sb */
+          *((FWORD *) dest_pos) = src_sb;
         }
       }
       dest_pos += (i < num_advances ? 4 : 2);
@@ -187,34 +186,27 @@
   {
     friend struct hmtxvmtx;
 
-    inline void init (hb_face_t *face,
+    void init (hb_face_t *face,
                       unsigned int default_advance_ = 0)
     {
       default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
 
       bool got_font_extents = false;
-      if (T::os2Tag)
+      if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ())
       {
-        hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
-        const os2 *os2_table = os2_blob->as<os2> ();
-#define USE_TYPO_METRICS (1u<<7)
-        if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
-        {
-          ascender = os2_table->sTypoAscender;
-          descender = os2_table->sTypoDescender;
-          line_gap = os2_table->sTypoLineGap;
-          got_font_extents = (ascender | descender) != 0;
-        }
-        hb_blob_destroy (os2_blob);
+        ascender = abs (face->table.OS2->sTypoAscender);
+        descender = -abs (face->table.OS2->sTypoDescender);
+        line_gap = face->table.OS2->sTypoLineGap;
+        got_font_extents = (ascender | descender) != 0;
       }
 
-      hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
+      hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
       const H *_hea_table = _hea_blob->as<H> ();
       num_advances = _hea_table->numberOfLongMetrics;
       if (!got_font_extents)
       {
-        ascender = _hea_table->ascender;
-        descender = _hea_table->descender;
+        ascender = abs (_hea_table->ascender);
+        descender = -abs (_hea_table->descender);
         line_gap = _hea_table->lineGap;
         got_font_extents = (ascender | descender) != 0;
       }
@@ -222,10 +214,10 @@
 
       has_font_extents = got_font_extents;
 
-      blob = Sanitizer<hmtxvmtx> ().sanitize (face->reference_table (T::tableTag));
+      table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
 
       /* Cap num_metrics() and num_advances() based on table length. */
-      unsigned int len = hb_blob_get_length (blob);
+      unsigned int len = table.get_length ();
       if (unlikely (num_advances * 4 > len))
         num_advances = len / 4;
       num_metrics = num_advances + (len - 4 * num_advances) / 2;
@@ -235,22 +227,33 @@
       if (unlikely (!num_advances))
       {
         num_metrics = num_advances = 0;
-        hb_blob_destroy (blob);
-        blob = hb_blob_get_empty ();
+        table.destroy ();
+        table = hb_blob_get_empty ();
       }
-      table = blob->as<hmtxvmtx> ();
+
+      var_table = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
+    }
 
-      var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
-      var_table = var_blob->as<HVARVVAR> ();
+    void fini ()
+    {
+      table.destroy ();
+      var_table.destroy ();
     }
 
-    inline void fini (void)
+    /* TODO Add variations version. */
+    unsigned int get_side_bearing (hb_codepoint_t glyph) const
     {
-      hb_blob_destroy (blob);
-      hb_blob_destroy (var_blob);
+      if (glyph < num_advances)
+        return table->longMetricZ[glyph].sb;
+
+      if (unlikely (glyph >= num_metrics))
+        return 0;
+
+      const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
+      return bearings[glyph - num_advances];
     }
 
-    inline unsigned int get_advance (hb_codepoint_t  glyph) const
+    unsigned int get_advance (hb_codepoint_t glyph) const
     {
       if (unlikely (glyph >= num_metrics))
       {
@@ -263,14 +266,14 @@
           return default_advance;
       }
 
-      return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance;
+      return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance;
     }
 
-    inline unsigned int get_advance (hb_codepoint_t  glyph,
-                                     hb_font_t      *font) const
+    unsigned int get_advance (hb_codepoint_t  glyph,
+                              hb_font_t      *font) const
     {
       unsigned int advance = get_advance (glyph);
-      if (likely(glyph < num_metrics))
+      if (likely (glyph < num_metrics))
       {
         advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
       }
@@ -279,9 +282,9 @@
 
     public:
     bool has_font_extents;
-    unsigned short ascender;
-    unsigned short descender;
-    unsigned short line_gap;
+    int ascender;
+    int descender;
+    int line_gap;
 
     protected:
     unsigned int num_metrics;
@@ -289,14 +292,12 @@
     unsigned int default_advance;
 
     private:
-    const hmtxvmtx *table;
-    hb_blob_t *blob;
-    const HVARVVAR *var_table;
-    hb_blob_t *var_blob;
+    hb_blob_ptr_t<hmtxvmtx> table;
+    hb_blob_ptr_t<HVARVVAR> var_table;
   };
 
   protected:
-  LongMetric    longMetric[VAR];        /* Paired advance width and leading
+  UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading
                                          * bearing values for each glyph. The
                                          * value numOfHMetrics comes from
                                          * the 'hhea' table. If the font is
@@ -304,7 +305,7 @@
                                          * be in the array, but that entry is
                                          * required. The last entry applies to
                                          * all subsequent glyphs. */
-/*FWORD         leadingBearingX[VAR];*/ /* Here the advance is assumed
+/*UnsizedArrayOf<FWORD> leadingBearingX;*//* Here the advance is assumed
                                          * to be the same as the advance
                                          * for the last entry above. The
                                          * number of entries in this array is
@@ -318,20 +319,23 @@
                                          * font to vary the side bearing
                                          * values for each glyph. */
   public:
-  DEFINE_SIZE_ARRAY (0, longMetric);
+  DEFINE_SIZE_ARRAY (0, longMetricZ);
 };
 
 struct hmtx : hmtxvmtx<hmtx, hhea> {
-  static const hb_tag_t tableTag        = HB_OT_TAG_hmtx;
-  static const hb_tag_t variationsTag   = HB_OT_TAG_HVAR;
-  static const hb_tag_t os2Tag          = HB_OT_TAG_os2;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
+  static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2;
 };
 struct vmtx : hmtxvmtx<vmtx, vhea> {
-  static const hb_tag_t tableTag        = HB_OT_TAG_vmtx;
-  static const hb_tag_t variationsTag   = HB_OT_TAG_VVAR;
-  static const hb_tag_t os2Tag          = HB_TAG_NONE;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
+  static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t os2Tag = HB_TAG_NONE;
 };
 
+struct hmtx_accelerator_t : hmtx::accelerator_t {};
+struct vmtx_accelerator_t : vmtx::accelerator_t {};
+
 } /* namespace OT */
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-kern-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-kern-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,8 @@
 #ifndef HB_OT_KERN_TABLE_HH
 #define HB_OT_KERN_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-aat-layout-kerx-table.hh"
+
 
 /*
  * kern -- Kerning
@@ -40,354 +41,297 @@
 namespace OT {
 
 
-struct hb_glyph_pair_t
+template <typename KernSubTableHeader>
+struct KernSubTableFormat3
 {
-  hb_codepoint_t left;
-  hb_codepoint_t right;
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+  {
+    hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
+    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (kernValue).as_array (glyphCount);
+    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (leftClass).as_array (glyphCount);
+    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8> > (rightClass).as_array (leftClassCount * rightClassCount);
+
+    unsigned int leftC = leftClass[left];
+    unsigned int rightC = rightClass[right];
+    if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
+      return 0;
+    unsigned int i = leftC * rightClassCount + rightC;
+    return kernValue[kernIndex[i]];
+  }
+
+  bool apply (AAT::hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+
+    if (!c->plan->requested_kerning)
+      return false;
+
+    if (header.coverage & header.Backwards)
+      return false;
+
+    hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
+    machine.kern (c->font, c->buffer, c->plan->kern_mask);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  c->check_range (kernValueZ,
+                                  kernValueCount * sizeof (FWORD) +
+                                  glyphCount * 2 +
+                                  leftClassCount * rightClassCount));
+  }
+
+  protected:
+  KernSubTableHeader    header;
+  HBUINT16              glyphCount;     /* The number of glyphs in this font. */
+  HBUINT8               kernValueCount; /* The number of kerning values. */
+  HBUINT8               leftClassCount; /* The number of left-hand classes. */
+  HBUINT8               rightClassCount;/* The number of right-hand classes. */
+  HBUINT8               flags;          /* Set to zero (reserved for future use). */
+  UnsizedArrayOf<FWORD> kernValueZ;     /* The kerning values.
+                                         * Length kernValueCount. */
+#if 0
+  UnsizedArrayOf<HBUINT8>leftClass;     /* The left-hand classes.
+                                         * Length glyphCount. */
+  UnsizedArrayOf<HBUINT8>rightClass;    /* The right-hand classes.
+                                         * Length glyphCount. */
+  UnsizedArrayOf<HBUINT8>kernIndex;     /* The indices into the kernValue array.
+                                         * Length leftClassCount * rightClassCount */
+#endif
+  public:
+  DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
 };
 
-struct KernPair
+template <typename KernSubTableHeader>
+struct KernSubTable
 {
-  inline int get_kerning (void) const
-  { return value; }
+  unsigned int get_size () const { return u.header.length; }
+  unsigned int get_type () const { return u.header.format; }
 
-  inline int cmp (const hb_glyph_pair_t &o) const
+  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   {
-    int ret = left.cmp (o.left);
-    if (ret) return ret;
-    return right.cmp (o.right);
+    switch (get_type ()) {
+    /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
+    case 0: return u.format0.get_kerning (left, right);
+    default:return 0;
+    }
+  }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case 0:     return_trace (c->dispatch (u.format0));
+    case 1:     return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ());
+    case 2:     return_trace (c->dispatch (u.format2));
+    case 3:     return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ());
+    default:    return_trace (c->default_return_value ());
+    }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!u.header.sanitize (c) ||
+                  u.header.length < u.header.min_size ||
+                  !c->check_range (this, u.header.length))) return_trace (false);
+
+    return_trace (dispatch (c));
+  }
+
+  public:
+  union {
+  KernSubTableHeader                            header;
+  AAT::KerxSubTableFormat0<KernSubTableHeader>  format0;
+  AAT::KerxSubTableFormat1<KernSubTableHeader>  format1;
+  AAT::KerxSubTableFormat2<KernSubTableHeader>  format2;
+  KernSubTableFormat3<KernSubTableHeader>       format3;
+  } u;
+  public:
+  DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
+};
+
+
+struct KernOTSubTableHeader
+{
+  static constexpr bool apple = false;
+  typedef AAT::ObsoleteTypes Types;
+
+  unsigned int tuple_count () const { return 0; }
+  bool is_horizontal () const { return (coverage & Horizontal); }
+
+  enum Coverage
+  {
+    Horizontal  = 0x01u,
+    Minimum     = 0x02u,
+    CrossStream = 0x04u,
+    Override    = 0x08u,
+
+    /* Not supported: */
+    Backwards   = 0x00u,
+    Variation   = 0x00u,
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  protected:
-  GlyphID       left;
-  GlyphID       right;
-  FWORD         value;
+  public:
+  HBUINT16      versionZ;       /* Unused. */
+  HBUINT16      length;         /* Length of the subtable (including this header). */
+  HBUINT8       format;         /* Subtable format. */
+  HBUINT8       coverage;       /* Coverage bits. */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
-struct KernSubTableFormat0
+struct KernOT : AAT::KerxTable<KernOT>
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-  {
-    hb_glyph_pair_t pair = {left, right};
-    int i = pairs.bsearch (pair);
-    if (i == -1)
-      return 0;
-    return pairs[i].get_kerning ();
-  }
+  friend struct AAT::KerxTable<KernOT>;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (pairs.sanitize (c));
-  }
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
+  static constexpr unsigned minVersion = 0u;
 
-  protected:
-  BinSearchArrayOf<KernPair> pairs;     /* Array of kerning pairs. */
-  public:
-  DEFINE_SIZE_ARRAY (8, pairs);
-};
-
-struct KernClassTable
-{
-  inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
-  }
+  typedef KernOTSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KernSubTable<SubTableHeader> SubTable;
 
   protected:
-  HBUINT16              firstGlyph;     /* First glyph in class range. */
-  ArrayOf<HBUINT16>     classes;        /* Glyph classes. */
+  HBUINT16      version;        /* Version--0x0000u */
+  HBUINT16      tableCount;     /* Number of subtables in the kerning table. */
+  SubTable      firstSubTable;  /* Subtables. */
   public:
-  DEFINE_SIZE_ARRAY (4, classes);
+  DEFINE_SIZE_MIN (4);
 };
 
-struct KernSubTableFormat2
+
+struct KernAATSubTableHeader
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
+  static constexpr bool apple = true;
+  typedef AAT::ObsoleteTypes Types;
+
+  unsigned int tuple_count () const { return 0; }
+  bool is_horizontal () const       { return !(coverage & Vertical); }
+
+  enum Coverage
   {
-    unsigned int l = (this+leftClassTable).get_class (left);
-    unsigned int r = (this+rightClassTable).get_class (right);
-    unsigned int offset = l * rowWidth + r * sizeof (FWORD);
-    const FWORD *arr = &(this+array);
-    if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
-      return 0;
-    const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
-    if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
-      return 0;
-    return *v;
+    Vertical    = 0x80u,
+    CrossStream = 0x40u,
+    Variation   = 0x20u,
+
+    /* Not supported: */
+    Backwards   = 0x00u,
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rowWidth.sanitize (c) &&
-                  leftClassTable.sanitize (c, this) &&
-                  rightClassTable.sanitize (c, this) &&
-                  array.sanitize (c, this));
-  }
+  public:
+  HBUINT32      length;         /* Length of the subtable (including this header). */
+  HBUINT8       coverage;       /* Coverage bits. */
+  HBUINT8       format;         /* Subtable format. */
+  HBUINT16      tupleIndex;     /* The tuple index (used for variations fonts).
+                               * This value specifies which tuple this subtable covers.
+                               * Note: We don't implement. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct KernAAT : AAT::KerxTable<KernAAT>
+{
+  friend struct AAT::KerxTable<KernAAT>;
+
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
+  static constexpr unsigned minVersion = 0x00010000u;
+
+  typedef KernAATSubTableHeader SubTableHeader;
+  typedef SubTableHeader::Types Types;
+  typedef KernSubTable<SubTableHeader> SubTable;
 
   protected:
-  HBUINT16      rowWidth;       /* The width, in bytes, of a row in the table. */
-  OffsetTo<KernClassTable>
-                leftClassTable; /* Offset from beginning of this subtable to
-                                 * left-hand class table. */
-  OffsetTo<KernClassTable>
-                rightClassTable;/* Offset from beginning of this subtable to
-                                 * right-hand class table. */
-  OffsetTo<FWORD>
-                array;          /* Offset from beginning of this subtable to
-                                 * the start of the kerning array. */
+  HBUINT32      version;        /* Version--0x00010000u */
+  HBUINT32      tableCount;     /* Number of subtables in the kerning table. */
+  SubTable      firstSubTable;  /* Subtables. */
   public:
   DEFINE_SIZE_MIN (8);
 };
 
-struct KernSubTable
+struct kern
 {
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
+
+  bool has_data () const { return u.version32; }
+  unsigned int get_type () const { return u.major; }
+
+  bool has_state_machine () const
   {
-    switch (format) {
-    case 0: return u.format0.get_kerning (left, right);
-    case 2: return u.format2.get_kerning (left, right, end);
+    switch (get_type ()) {
+    case 0: return u.ot.has_state_machine ();
+    case 1: return u.aat.has_state_machine ();
+    default:return false;
+    }
+  }
+
+  bool has_cross_stream () const
+  {
+    switch (get_type ()) {
+    case 0: return u.ot.has_cross_stream ();
+    case 1: return u.aat.has_cross_stream ();
+    default:return false;
+    }
+  }
+
+  int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
+  {
+    switch (get_type ()) {
+    case 0: return u.ot.get_h_kerning (left, right);
+    case 1: return u.aat.get_h_kerning (left, right);
     default:return 0;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
+  bool apply (AAT::hb_aat_apply_context_t *c) const
+  { return dispatch (c); }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int subtable_type = get_type ();
+    TRACE_DISPATCH (this, subtable_type);
+    switch (subtable_type) {
+    case 0:     return_trace (c->dispatch (u.ot));
+    case 1:     return_trace (c->dispatch (u.aat));
+    default:    return_trace (c->default_return_value ());
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    switch (format) {
-    case 0: return_trace (u.format0.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
+    if (!u.version32.sanitize (c)) return_trace (false);
+    return_trace (dispatch (c));
   }
 
   protected:
   union {
-  KernSubTableFormat0   format0;
-  KernSubTableFormat2   format2;
-  } u;
-  public:
-  DEFINE_SIZE_MIN (0);
-};
-
-
-template <typename T>
-struct KernSubTableWrapper
-{
-  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-  inline const T* thiz (void) const { return static_cast<const T *> (this); }
-
-  inline bool is_horizontal (void) const
-  { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; }
-
-  inline bool is_override (void) const
-  { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); }
-
-  inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); }
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
-  { return is_horizontal () ? get_kerning (left, right, end) : 0; }
-
-  inline unsigned int get_size (void) const { return thiz()->length; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (thiz()) &&
-                  thiz()->length >= T::min_size &&
-                  c->check_array (thiz(), 1, thiz()->length) &&
-                  thiz()->subtable.sanitize (c, thiz()->format));
-  }
-};
-
-template <typename T>
-struct KernTable
-{
-  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-  inline const T* thiz (void) const { return static_cast<const T *> (this); }
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
-  {
-    int v = 0;
-    const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
-    unsigned int count = thiz()->nTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (st->is_override ())
-        v = 0;
-      v += st->get_h_kerning (left, right, table_length + (const char *) this);
-      st = &StructAfter<typename T::SubTableWrapper> (*st);
-    }
-    return v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (thiz()) ||
-                  thiz()->version != T::VERSION))
-      return_trace (false);
-
-    const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
-    unsigned int count = thiz()->nTables;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (unlikely (!st->sanitize (c)))
-        return_trace (false);
-      st = &StructAfter<typename T::SubTableWrapper> (*st);
-    }
-
-    return_trace (true);
-  }
-};
-
-struct KernOT : KernTable<KernOT>
-{
-  friend struct KernTable<KernOT>;
-
-  static const uint16_t VERSION = 0x0000u;
-
-  struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
-  {
-    friend struct KernSubTableWrapper<SubTableWrapper>;
-
-    enum coverage_flags_t {
-      COVERAGE_DIRECTION_FLAG   = 0x01u,
-      COVERAGE_MINIMUM_FLAG     = 0x02u,
-      COVERAGE_CROSSSTREAM_FLAG = 0x04u,
-      COVERAGE_OVERRIDE_FLAG    = 0x08u,
-
-      COVERAGE_VARIATION_FLAG   = 0x00u, /* Not supported. */
-
-      COVERAGE_CHECK_FLAGS      = 0x07u,
-      COVERAGE_CHECK_HORIZONTAL = 0x01u
-    };
-
-    protected:
-    HBUINT16    versionZ;       /* Unused. */
-    HBUINT16    length;         /* Length of the subtable (including this header). */
-    HBUINT8     format;         /* Subtable format. */
-    HBUINT8     coverage;       /* Coverage bits. */
-    KernSubTable subtable;      /* Subtable data. */
-    public:
-    DEFINE_SIZE_MIN (6);
-  };
-
-  protected:
-  HBUINT16      version;        /* Version--0x0000u */
-  HBUINT16      nTables;        /* Number of subtables in the kerning table. */
-  HBUINT8               data[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (4, data);
-};
-
-struct KernAAT : KernTable<KernAAT>
-{
-  friend struct KernTable<KernAAT>;
-
-  static const uint32_t VERSION = 0x00010000u;
-
-  struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
-  {
-    friend struct KernSubTableWrapper<SubTableWrapper>;
-
-    enum coverage_flags_t {
-      COVERAGE_DIRECTION_FLAG   = 0x80u,
-      COVERAGE_CROSSSTREAM_FLAG = 0x40u,
-      COVERAGE_VARIATION_FLAG   = 0x20u,
-
-      COVERAGE_OVERRIDE_FLAG    = 0x00u, /* Not supported. */
-
-      COVERAGE_CHECK_FLAGS      = 0xE0u,
-      COVERAGE_CHECK_HORIZONTAL = 0x00u
-    };
-
-    protected:
-    HBUINT32    length;         /* Length of the subtable (including this header). */
-    HBUINT8     coverage;       /* Coverage bits. */
-    HBUINT8     format;         /* Subtable format. */
-    HBUINT16    tupleIndex;     /* The tuple index (used for variations fonts).
-                                 * This value specifies which tuple this subtable covers. */
-    KernSubTable subtable;      /* Subtable data. */
-    public:
-    DEFINE_SIZE_MIN (8);
-  };
-
-  protected:
-  HBUINT32              version;        /* Version--0x00010000u */
-  HBUINT32              nTables;        /* Number of subtables in the kerning table. */
-  HBUINT8               data[VAR];
-  public:
-  DEFINE_SIZE_ARRAY (8, data);
-};
-
-struct kern
-{
-  static const hb_tag_t tableTag = HB_OT_TAG_kern;
-
-  inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
-  {
-    switch (u.major) {
-    case 0: return u.ot.get_h_kerning (left, right, table_length);
-    case 1: return u.aat.get_h_kerning (left, right, table_length);
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.major.sanitize (c)) return_trace (false);
-    switch (u.major) {
-    case 0: return_trace (u.ot.sanitize (c));
-    case 1: return_trace (u.aat.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  struct accelerator_t
-  {
-    inline void init (hb_face_t *face)
-    {
-      blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
-      table = blob->as<kern> ();
-      table_length = blob->length;
-    }
-    inline void fini (void)
-    {
-      hb_blob_destroy (blob);
-    }
-
-    inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-    { return table->get_h_kerning (left, right, table_length); }
-
-    private:
-    hb_blob_t *blob;
-    const kern *table;
-    unsigned int table_length;
-  };
-
-  protected:
-  union {
+  HBUINT32              version32;
   HBUINT16              major;
   KernOT                ot;
   KernAAT               aat;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, major);
+  DEFINE_SIZE_UNION (4, version32);
 };
 
 } /* namespace OT */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-base-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-base-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -1,6 +1,7 @@
 /*
  * Copyright © 2016 Elie Roux <elie.roux@telecom-bretagne.eu>
  * Copyright © 2018  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -28,13 +29,14 @@
 #ifndef HB_OT_LAYOUT_BASE_TABLE_HH
 #define HB_OT_LAYOUT_BASE_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-common-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+
+/* To be removed */
+typedef hb_tag_t hb_ot_layout_baseline_t;
 
 namespace OT {
 
-#define NOT_INDEXED   ((unsigned int) -1)
-
 /*
  * BASE -- Baseline
  * https://docs.microsoft.com/en-us/typography/opentype/spec/base
@@ -42,30 +44,30 @@
 
 struct BaseCoordFormat1
 {
-  inline int get_coord (void) const { return coordinate; }
+  hb_position_t get_coord () const { return coordinate; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    return_trace (likely (c->check_struct (this)));
   }
 
   protected:
   HBUINT16      format;         /* Format identifier--format = 1 */
-  HBINT16       coordinate;     /* X or Y value, in design units */
+  FWORD         coordinate;     /* X or Y value, in design units */
   public:
   DEFINE_SIZE_STATIC (4);
 };
 
 struct BaseCoordFormat2
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord () const
   {
     /* TODO */
     return coordinate;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -73,7 +75,7 @@
 
   protected:
   HBUINT16      format;         /* Format identifier--format = 2 */
-  HBINT16       coordinate;     /* X or Y value, in design units */
+  FWORD         coordinate;     /* X or Y value, in design units */
   GlyphID       referenceGlyph; /* Glyph ID of control glyph */
   HBUINT16      coordPoint;     /* Index of contour point on the
                                  * reference glyph */
@@ -83,44 +85,53 @@
 
 struct BaseCoordFormat3
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord (hb_font_t *font,
+                           const VariationStore &var_store,
+                           hb_direction_t direction) const
   {
-    /* TODO */
-    return coordinate;
+    const Device &device = this+deviceTable;
+    return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ?
+                         device.get_y_delta (font, var_store) :
+                         device.get_x_delta (font, var_store));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          deviceTable.sanitize (c, this)));
   }
 
   protected:
-  HBUINT16              format;         /* Format identifier--format = 3 */
-  HBINT16               coordinate;     /* X or Y value, in design units */
-  OffsetTo<Device>      deviceTable;    /* Offset to Device table for X or
-                                         * Y value, from beginning of
-                                         * BaseCoord table (may be NULL). */
+  HBUINT16      format;         /* Format identifier--format = 3 */
+  FWORD         coordinate;     /* X or Y value, in design units */
+  OffsetTo<Device>
+                deviceTable;    /* Offset to Device table for X or
+                                 * Y value, from beginning of
+                                 * BaseCoord table (may be NULL). */
   public:
   DEFINE_SIZE_STATIC (6);
 };
 
 struct BaseCoord
 {
-  inline int get_coord (void) const
+  hb_position_t get_coord (hb_font_t *font,
+                           const VariationStore &var_store,
+                           hb_direction_t direction) const
   {
     switch (u.format) {
     case 1: return u.format1.get_coord ();
     case 2: return u.format2.get_coord ();
-    case 3: return u.format3.get_coord ();
+    case 3: return u.format3.get_coord (font, var_store, direction);
     default:return 0;
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
+    if (unlikely (!u.format.sanitize (c))) return_trace (false);
     switch (u.format) {
     case 1: return_trace (u.format1.sanitize (c));
     case 2: return_trace (u.format2.sanitize (c));
@@ -142,32 +153,40 @@
 
 struct FeatMinMaxRecord
 {
-  inline int get_min_value (void) const
-  { return (this+minCoord).get_coord(); }
+  static int cmp (const void *key_, const void *entry_)
+  {
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_;
+    return key < (unsigned int) entry.tag ? -1 :
+           key > (unsigned int) entry.tag ? 1 :
+           0;
+  }
 
-  inline int get_max_value (void) const
-  { return (this+maxCoord).get_coord(); }
+  void get_min_max (const BaseCoord **min, const BaseCoord **max) const
+  {
+    if (likely (min)) *min = &(this+minCoord);
+    if (likely (max)) *max = &(this+maxCoord);
+  }
 
-  inline const Tag &get_tag () const
-  { return tag; }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  minCoord.sanitize (c, base) &&
-                  maxCoord.sanitize (c, base));
+    return_trace (likely (c->check_struct (this) &&
+                          minCoord.sanitize (c, this) &&
+                          maxCoord.sanitize (c, this)));
   }
 
   protected:
-  Tag                   tag;            /* 4-byte feature identification tag--must
-                                         * match feature tag in FeatureList */
-  OffsetTo<BaseCoord>   minCoord;       /* Offset to BaseCoord table that defines
-                                         * the minimum extent value, from beginning
-                                         * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>   maxCoord;       /* Offset to BaseCoord table that defines
-                                         * the maximum extent value, from beginning
-                                         * of MinMax table (may be NULL) */
+  Tag           tag;            /* 4-byte feature identification tag--must
+                                 * match feature tag in FeatureList */
+  OffsetTo<BaseCoord>
+                minCoord;       /* Offset to BaseCoord table that defines
+                                 * the minimum extent value, from beginning
+                                 * of MinMax table (may be NULL) */
+  OffsetTo<BaseCoord>
+                maxCoord;       /* Offset to BaseCoord table that defines
+                                 * the maximum extent value, from beginning
+                                 * of MinMax table (may be NULL) */
   public:
   DEFINE_SIZE_STATIC (8);
 
@@ -175,356 +194,269 @@
 
 struct MinMax
 {
-  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
+  void get_min_max (hb_tag_t          feature_tag,
+                           const BaseCoord **min,
+                           const BaseCoord **max) const
   {
-    /* TODO bsearch */
-    unsigned int count = featMinMaxRecords.len;
-    for (unsigned int i = 0; i < count; i++)
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    const FeatMinMaxRecord *minMaxCoord = (const FeatMinMaxRecord *)
+                                          hb_bsearch (&feature_tag, featMinMaxRecords.arrayZ,
+                                                      featMinMaxRecords.len,
+                                                      FeatMinMaxRecord::static_size,
+                                                      FeatMinMaxRecord::cmp);
+    if (minMaxCoord)
+      minMaxCoord->get_min_max (min, max);
+    else
     {
-      Tag tag = featMinMaxRecords[i].get_tag();
-      int cmp = tag.cmp(featureTableTag);
-      if (cmp == 0) return i;
-      if (cmp > 0)  return NOT_INDEXED;
+      if (likely (min)) *min = &(this+minCoord);
+      if (likely (max)) *max = &(this+maxCoord);
     }
-    return NOT_INDEXED;
   }
 
-  inline int get_min_value (unsigned int featureTableTagIndex) const
-  {
-    if (featureTableTagIndex == NOT_INDEXED)
-      return (this+minCoord).get_coord();
-    return featMinMaxRecords[featureTableTagIndex].get_min_value();
-  }
-
-  inline int get_max_value (unsigned int featureTableTagIndex) const
-  {
-    if (featureTableTagIndex == NOT_INDEXED)
-      return (this+maxCoord).get_coord();
-    return featMinMaxRecords[featureTableTagIndex].get_max_value();
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  minCoord.sanitize (c, this) &&
-                  maxCoord.sanitize (c, this) &&
-                  featMinMaxRecords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          minCoord.sanitize (c, this) &&
+                          maxCoord.sanitize (c, this) &&
+                          featMinMaxRecords.sanitize (c, this)));
   }
 
   protected:
-  OffsetTo<BaseCoord>   minCoord;       /* Offset to BaseCoord table that defines
-                                         * minimum extent value, from the beginning
-                                         * of MinMax table (may be NULL) */
-  OffsetTo<BaseCoord>   maxCoord;       /* Offset to BaseCoord table that defines
-                                         * maximum extent value, from the beginning
-                                         * of MinMax table (may be NULL) */
-  ArrayOf<FeatMinMaxRecord>
-                featMinMaxRecords;      /* Array of FeatMinMaxRecords, in alphabetical
-                                         * order by featureTableTag */
+  OffsetTo<BaseCoord>
+                minCoord;       /* Offset to BaseCoord table that defines
+                                 * minimum extent value, from the beginning
+                                 * of MinMax table (may be NULL) */
+  OffsetTo<BaseCoord>
+                maxCoord;       /* Offset to BaseCoord table that defines
+                                 * maximum extent value, from the beginning
+                                 * of MinMax table (may be NULL) */
+  SortedArrayOf<FeatMinMaxRecord>
+                featMinMaxRecords;
+                                /* Array of FeatMinMaxRecords, in alphabetical
+                                 * order by featureTableTag */
   public:
   DEFINE_SIZE_ARRAY (6, featMinMaxRecords);
 };
 
-/* TODO... */
-struct BaseLangSysRecord
-{
-  inline const Tag& get_tag(void) const
-  { return baseLangSysTag; }
-
-  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
-  { return (this+minMax).get_feature_tag_index(featureTableTag); }
-
-  inline int get_min_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_min_value(featureTableTagIndex); }
-
-  inline int get_max_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_max_value(featureTableTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  minMax.sanitize (c, base));
-  }
-
-  protected:
-  Tag                   baseLangSysTag;
-  OffsetTo<MinMax>      minMax;
-  public:
-  DEFINE_SIZE_STATIC (6);
-
-};
-
 struct BaseValues
 {
-  inline unsigned int get_default_base_tag_index (void) const
-  { return defaultIndex; }
-
-  inline int get_base_coord (unsigned int baselineTagIndex) const
+  const BaseCoord &get_base_coord (int baseline_tag_index) const
   {
-    return (this+baseCoords[baselineTagIndex]).get_coord();
+    if (baseline_tag_index == -1) baseline_tag_index = defaultIndex;
+    return this+baseCoords[baseline_tag_index];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      defaultIndex <= baseCoordCount &&
-      baseCoords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          baseCoords.sanitize (c, this)));
   }
 
   protected:
-  Index                         defaultIndex;
-  HBUINT16                      baseCoordCount;
-  OffsetArrayOf<BaseCoord>      baseCoords;
+  Index         defaultIndex;   /* Index number of default baseline for this
+                                 * script — equals index position of baseline tag
+                                 * in baselineTags array of the BaseTagList */
+  OffsetArrayOf<BaseCoord>
+                baseCoords;     /* Number of BaseCoord tables defined — should equal
+                                 * baseTagCount in the BaseTagList
+                                 *
+                                 * Array of offsets to BaseCoord tables, from beginning of
+                                 * BaseValues table — order matches baselineTags array in
+                                 * the BaseTagList */
   public:
-  DEFINE_SIZE_ARRAY (6, baseCoords);
-
+  DEFINE_SIZE_ARRAY (4, baseCoords);
 };
 
-struct BaseScript {
-
-  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
+struct BaseLangSysRecord
+{
+  static int cmp (const void *key_, const void *entry_)
   {
-    Tag tag;
-    int cmp;
-    for (unsigned int i = 0; i < baseLangSysCount; i++) {
-      tag = baseLangSysRecords[i].get_tag();
-      // taking advantage of alphabetical order
-      cmp = tag.cmp(baseLangSysTag);
-      if (cmp == 0) return i;
-      if (cmp > 0)  return NOT_INDEXED;
-    }
-    return NOT_INDEXED;
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_;
+    return key < (unsigned int) entry.baseLangSysTag ? -1 :
+           key > (unsigned int) entry.baseLangSysTag ? 1 :
+           0;
   }
 
-  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED) {
-      if (unlikely(defaultMinMax)) return NOT_INDEXED;
-      return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
-    }
-    if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
-    return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
-  }
+  const MinMax &get_min_max () const
+  { return this+minMax; }
 
-  inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
-  }
-
-  inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
-  }
-
-  inline unsigned int get_default_base_tag_index (void) const
-  { return (this+baseValues).get_default_base_tag_index(); }
-
-  inline int get_base_coord (unsigned int baselineTagIndex) const
-  { return (this+baseValues).get_base_coord(baselineTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseValues.sanitize (c, this) &&
-      defaultMinMax.sanitize (c, this) &&
-      baseLangSysRecords.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          minMax.sanitize (c, this)));
   }
 
   protected:
-  OffsetTo<BaseValues>        baseValues;
-  OffsetTo<MinMax>            defaultMinMax;
-  HBUINT16                      baseLangSysCount;
-  ArrayOf<BaseLangSysRecord>  baseLangSysRecords;
-
+  Tag           baseLangSysTag; /* 4-byte language system identification tag */
+  OffsetTo<MinMax>
+                minMax;         /* Offset to MinMax table, from beginning
+                                 * of BaseScript table */
   public:
-    DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
+  DEFINE_SIZE_STATIC (6);
 };
 
-
-struct BaseScriptRecord {
-
-  inline const Tag& get_tag (void) const
-  { return baseScriptTag; }
-
-  inline unsigned int get_default_base_tag_index(void) const
-  { return (this+baseScript).get_default_base_tag_index(); }
-
-  inline int get_base_coord(unsigned int baselineTagIndex) const
-  { return (this+baseScript).get_base_coord(baselineTagIndex); }
+struct BaseScript
+{
+  const MinMax &get_min_max (hb_tag_t language_tag) const
+  {
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    const BaseLangSysRecord* record = (const BaseLangSysRecord *)
+                                      hb_bsearch (&language_tag, baseLangSysRecords.arrayZ,
+                                                  baseLangSysRecords.len,
+                                                  BaseLangSysRecord::static_size,
+                                                  BaseLangSysRecord::cmp);
+    return record ? record->get_min_max () : this+defaultMinMax;
+  }
 
-  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
-  { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
-
-  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
+  const BaseCoord &get_base_coord (int baseline_tag_index) const
+  { return (this+baseValues).get_base_coord (baseline_tag_index); }
 
-  inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
+  bool is_empty () const { return !baseValues; }
 
-  inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseScript != Null(OffsetTo<BaseScript>) &&
-      baseScript.sanitize (c, base));
+    return_trace (likely (c->check_struct (this) &&
+                          baseValues.sanitize (c, this) &&
+                          defaultMinMax.sanitize (c, this) &&
+                          baseLangSysRecords.sanitize (c, this)));
   }
 
   protected:
-  Tag                   baseScriptTag;
-  OffsetTo<BaseScript>  baseScript;
+  OffsetTo<BaseValues>
+                baseValues;     /* Offset to BaseValues table, from beginning
+                                 * of BaseScript table (may be NULL) */
+  OffsetTo<MinMax>
+                defaultMinMax;  /* Offset to MinMax table, from beginning of
+                                 * BaseScript table (may be NULL) */
+  SortedArrayOf<BaseLangSysRecord>
+                baseLangSysRecords;
+                                /* Number of BaseLangSysRecords
+                                 * defined — may be zero (0) */
 
   public:
-    DEFINE_SIZE_STATIC (6);
+  DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
 };
 
-struct BaseScriptList {
-
-  inline unsigned int get_base_script_index (Tag baseScriptTag) const
+struct BaseScriptList;
+struct BaseScriptRecord
+{
+  static int cmp (const void *key_, const void *entry_)
   {
-    for (unsigned int i = 0; i < baseScriptCount; i++)
-      if (baseScriptRecords[i].get_tag() == baseScriptTag)
-        return i;
-    return NOT_INDEXED;
-  }
-
-  inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
+    hb_tag_t key = * (hb_tag_t *) key_;
+    const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_;
+    return key < (unsigned int) entry.baseScriptTag ? -1 :
+           key > (unsigned int) entry.baseScriptTag ? 1 :
+           0;
   }
 
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex);
-  }
+  const BaseScript &get_base_script (const BaseScriptList *list) const
+  { return list+baseScript; }
 
-  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          baseScript.sanitize (c, base)));
   }
 
-  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  protected:
+  Tag           baseScriptTag;  /* 4-byte script identification tag */
+  OffsetTo<BaseScript>
+                baseScript;     /* Offset to BaseScript table, from beginning
+                                 * of BaseScriptList */
+
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct BaseScriptList
+{
+  const BaseScriptRecord *find_record (hb_tag_t script) const
   {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
-    return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
+    /* TODO Replace hb_bsearch() with .bsearch(). */
+    return (const BaseScriptRecord *) hb_bsearch (&script, baseScriptRecords.arrayZ,
+                                                  baseScriptRecords.len,
+                                                  BaseScriptRecord::static_size,
+                                                  BaseScriptRecord::cmp);
   }
 
-  inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  /* TODO: Or client should handle fallback? */
+  const BaseScript &get_base_script (hb_tag_t script) const
   {
-    return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex);
+    const BaseScriptRecord *record = find_record (script);
+    if (!record) record = find_record ((hb_script_t) HB_TAG ('D','F','L','T'));
+
+    return record ? record->get_base_script (this) : Null (BaseScript);
   }
 
-  inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseScriptRecords.sanitize (c, this));
+                  baseScriptRecords.sanitize (c, this));
   }
 
   protected:
-  HBUINT16                    baseScriptCount;
-  ArrayOf<BaseScriptRecord> baseScriptRecords;
+  SortedArrayOf<BaseScriptRecord>
+                        baseScriptRecords;
 
   public:
-  DEFINE_SIZE_ARRAY (4, baseScriptRecords);
-
-};
-
-struct BaseTagList
-{
-
-  inline unsigned int get_tag_index(Tag baselineTag) const
-  {
-    for (unsigned int i = 0; i < baseTagCount; i++)
-      if (baselineTags[i] == baselineTag)
-        return i;
-    return NOT_INDEXED;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16        baseTagCount;
-  SortedArrayOf<Tag>  baselineTags;
-
-  public:
-  DEFINE_SIZE_ARRAY (4, baselineTags);
+  DEFINE_SIZE_ARRAY (2, baseScriptRecords);
 };
 
 struct Axis
 {
-
-  inline unsigned int get_base_tag_index(Tag baselineTag) const
+  bool get_baseline (hb_ot_layout_baseline_t   baseline,
+                            hb_tag_t                  script_tag,
+                            hb_tag_t                  language_tag,
+                            const BaseCoord         **coord) const
   {
-    if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
-    return (this+baseTagList).get_tag_index(baselineTag);
-  }
+    const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
+    if (base_script.is_empty ()) return false;
 
-  inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
-  }
+    if (likely (coord)) *coord = &base_script.get_base_coord ((this+baseTagList).bsearch (baseline));
 
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
+    return true;
   }
 
-  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  bool get_min_max (hb_tag_t          script_tag,
+                    hb_tag_t          language_tag,
+                    hb_tag_t          feature_tag,
+                    const BaseCoord **min_coord,
+                    const BaseCoord **max_coord) const
   {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
-  }
+    const BaseScript &base_script = (this+baseScriptList).get_base_script (script_tag);
+    if (base_script.is_empty ()) return false;
 
-  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
-    return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
+    base_script.get_min_max (language_tag).get_min_max (feature_tag, min_coord, max_coord);
+
+    return true;
   }
 
-  inline int get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseTagList.sanitize (c, this) &&
-      baseScriptList.sanitize (c, this));
+    return_trace (likely (c->check_struct (this) &&
+                          (this+baseTagList).sanitize (c) &&
+                          (this+baseScriptList).sanitize (c)));
   }
 
   protected:
-  OffsetTo<BaseTagList>     baseTagList;
-  OffsetTo<BaseScriptList>  baseScriptList;
+  OffsetTo<SortedArrayOf<Tag> >
+                baseTagList;    /* Offset to BaseTagList table, from beginning
+                                 * of Axis table (may be NULL)
+                                 * Array of 4-byte baseline identification tags — must
+                                 * be in alphabetical order */
+  OffsetTo<BaseScriptList>
+                baseScriptList; /* Offset to BaseScriptList table, from beginning
+                                 * of Axis table
+                                 * Array of BaseScriptRecords, in alphabetical order
+                                 * by baseScriptTag */
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -532,119 +464,72 @@
 
 struct BASE
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_BASE;
-
-  inline bool has_vert_axis(void)
-  { return vertAxis != Null(OffsetTo<Axis>); }
-
-  inline bool has_horiz_axis(void)
-  { return horizAxis != Null(OffsetTo<Axis>); }
-
-  // horizontal axis base coords:
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_BASE;
 
-  inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_base_tag_index(baselineTag);
-  }
+  const Axis &get_axis (hb_direction_t direction) const
+  { return HB_DIRECTION_IS_VERTICAL (direction) ? this+vAxis : this+hAxis; }
 
-  inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
-  }
+  const VariationStore &get_var_store () const
+  { return version.to_int () < 0x00010001u ? Null (VariationStore) : this+varStore; }
 
-  inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
-  }
-
-  // vertical axis base coords:
-
-  inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
+  bool get_baseline (hb_font_t               *font,
+                     hb_ot_layout_baseline_t  baseline,
+                     hb_direction_t           direction,
+                     hb_tag_t                 script_tag,
+                     hb_tag_t                 language_tag,
+                     hb_position_t           *base) const
   {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_base_tag_index(baselineTag);
-  }
+    const BaseCoord *base_coord;
+    if (!get_axis (direction).get_baseline (baseline, script_tag, language_tag, &base_coord))
+      return false;
 
-  inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
-  }
-
-  inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
-  {
-    return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+    if (likely (base && base_coord)) *base = base_coord->get_coord (font,
+                                                                    get_var_store (),
+                                                                    direction);
+    return true;
   }
 
-  // horizontal axis min/max coords:
-
-  inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  /* TODO: Expose this separately sometime? */
+  bool get_min_max (hb_font_t      *font,
+                    hb_direction_t  direction,
+                    hb_tag_t        script_tag,
+                    hb_tag_t        language_tag,
+                    hb_tag_t        feature_tag,
+                    hb_position_t  *min,
+                    hb_position_t  *max)
   {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
+    const BaseCoord *min_coord, *max_coord;
+    if (!get_axis (direction).get_min_max (script_tag, language_tag, feature_tag,
+                                           &min_coord, &max_coord))
+      return false;
 
-  inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+    const VariationStore &var_store = get_var_store ();
+    if (likely (min && min_coord)) *min = min_coord->get_coord (font, var_store, direction);
+    if (likely (max && max_coord)) *max = max_coord->get_coord (font, var_store, direction);
+    return true;
   }
 
-    // vertical axis min/max coords:
-
-  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
-  }
-
-  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
-    return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
-  }
-
-  inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  {
-    return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  likely (version.major == 1) &&
-                  horizAxis.sanitize (c, this) &&
-                  vertAxis.sanitize (c, this) &&
-                  (version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
+    return_trace (likely (c->check_struct (this) &&
+                          likely (version.major == 1) &&
+                          hAxis.sanitize (c, this) &&
+                          vAxis.sanitize (c, this) &&
+                          (version.to_int () < 0x00010001u || varStore.sanitize (c, this))));
   }
 
   protected:
-  FixedVersion<>  version;
-  OffsetTo<Axis>  horizAxis;
-  OffsetTo<Axis>  vertAxis;
+  FixedVersion<>version;        /* Version of the BASE table */
+  OffsetTo<Axis>hAxis;          /* Offset to horizontal Axis table, from beginning
+                                 * of BASE table (may be NULL) */
+  OffsetTo<Axis>vAxis;          /* Offset to vertical Axis table, from beginning
+                                 * of BASE table (may be NULL) */
   LOffsetTo<VariationStore>
-                varStore;               /* Offset to the table of Item Variation
-                                         * Store--from beginning of BASE
-                                         * header (may be NULL).  Introduced
-                                         * in version 0x00010001. */
+                varStore;       /* Offset to the table of Item Variation
+                                 * Store--from beginning of BASE
+                                 * header (may be NULL).  Introduced
+                                 * in version 0x00010001. */
   public:
   DEFINE_SIZE_MIN (8);
 };
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1786 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
-#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-ot-layout-private.hh"
-#include "hb-open-type-private.hh"
-#include "hb-set-private.hh"
-
-
-#ifndef HB_MAX_NESTING_LEVEL
-#define HB_MAX_NESTING_LEVEL    6
-#endif
-#ifndef HB_MAX_CONTEXT_LENGTH
-#define HB_MAX_CONTEXT_LENGTH   64
-#endif
-
-
-namespace OT {
-
-
-#define NOT_COVERED             ((unsigned int) -1)
-
-
-
-/*
- *
- * OpenType Layout Common Table Formats
- *
- */
-
-
-/*
- * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
- */
-
-template <typename Type>
-struct Record
-{
-  inline int cmp (hb_tag_t a) const {
-    return tag.cmp (a);
-  }
-
-  struct sanitize_closure_t {
-    hb_tag_t tag;
-    const void *list_base;
-  };
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    const sanitize_closure_t closure = {tag, base};
-    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
-  }
-
-  Tag           tag;            /* 4-byte Tag identifier */
-  OffsetTo<Type>
-                offset;         /* Offset from beginning of object holding
-                                 * the Record */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-template <typename Type>
-struct RecordArrayOf : SortedArrayOf<Record<Type> > {
-  inline const Tag& get_tag (unsigned int i) const
-  {
-    /* We cheat slightly and don't define separate Null objects
-     * for Record types.  Instead, we return the correct Null(Tag)
-     * here. */
-    if (unlikely (i >= this->len)) return Null(Tag);
-    return (*this)[i].tag;
-  }
-  inline unsigned int get_tags (unsigned int start_offset,
-                                unsigned int *record_count /* IN/OUT */,
-                                hb_tag_t     *record_tags /* OUT */) const
-  {
-    if (record_count) {
-      const Record<Type> *arr = this->sub_array (start_offset, record_count);
-      unsigned int count = *record_count;
-      for (unsigned int i = 0; i < count; i++)
-        record_tags[i] = arr[i].tag;
-    }
-    return this->len;
-  }
-  inline bool find_index (hb_tag_t tag, unsigned int *index) const
-  {
-    /* If we want to allow non-sorted data, we can lsearch(). */
-    int i = this->/*lsearch*/bsearch (tag);
-    if (i != -1) {
-        if (index) *index = i;
-        return true;
-    } else {
-      if (index) *index = Index::NOT_FOUND_INDEX;
-      return false;
-    }
-  }
-};
-
-template <typename Type>
-struct RecordListOf : RecordArrayOf<Type>
-{
-  inline const Type& operator [] (unsigned int i) const
-  { return this+RecordArrayOf<Type>::operator [](i).offset; }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (RecordArrayOf<Type>::sanitize (c, this));
-  }
-};
-
-
-struct RangeRecord
-{
-  inline int cmp (hb_codepoint_t g) const {
-    return g < start ? -1 : g <= end ? 0 : +1 ;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  inline bool intersects (const hb_set_t *glyphs) const {
-    return glyphs->intersects (start, end);
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    return glyphs->add_range (start, end);
-  }
-
-  GlyphID       start;          /* First GlyphID in the range */
-  GlyphID       end;            /* Last GlyphID in the range */
-  HBUINT16      value;          /* Value */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-DEFINE_NULL_DATA (OT, RangeRecord, "\000\001");
-
-
-struct IndexArray : ArrayOf<Index>
-{
-  inline unsigned int get_indexes (unsigned int start_offset,
-                                   unsigned int *_count /* IN/OUT */,
-                                   unsigned int *_indexes /* OUT */) const
-  {
-    if (_count) {
-      const HBUINT16 *arr = this->sub_array (start_offset, _count);
-      unsigned int count = *_count;
-      for (unsigned int i = 0; i < count; i++)
-        _indexes[i] = arr[i];
-    }
-    return this->len;
-  }
-};
-
-
-struct Script;
-struct LangSys;
-struct Feature;
-
-
-struct LangSys
-{
-  inline unsigned int get_feature_count (void) const
-  { return featureIndex.len; }
-  inline hb_tag_t get_feature_index (unsigned int i) const
-  { return featureIndex[i]; }
-  inline unsigned int get_feature_indexes (unsigned int start_offset,
-                                           unsigned int *feature_count /* IN/OUT */,
-                                           unsigned int *feature_indexes /* OUT */) const
-  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
-
-  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
-  inline unsigned int get_required_feature_index (void) const
-  {
-    if (reqFeatureIndex == 0xFFFFu)
-      return Index::NOT_FOUND_INDEX;
-   return reqFeatureIndex;;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<LangSys>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
-  }
-
-  Offset16      lookupOrderZ;   /* = Null (reserved for an offset to a
-                                 * reordering table) */
-  HBUINT16      reqFeatureIndex;/* Index of a feature required for this
-                                 * language system--if no required features
-                                 * = 0xFFFFu */
-  IndexArray    featureIndex;   /* Array of indices into the FeatureList */
-  public:
-  DEFINE_SIZE_ARRAY (6, featureIndex);
-};
-DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF");
-
-
-struct Script
-{
-  inline unsigned int get_lang_sys_count (void) const
-  { return langSys.len; }
-  inline const Tag& get_lang_sys_tag (unsigned int i) const
-  { return langSys.get_tag (i); }
-  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
-                                         unsigned int *lang_sys_count /* IN/OUT */,
-                                         hb_tag_t     *lang_sys_tags /* OUT */) const
-  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
-  inline const LangSys& get_lang_sys (unsigned int i) const
-  {
-    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
-    return this+langSys[i].offset;
-  }
-  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
-  { return langSys.find_index (tag, index); }
-
-  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
-  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<Script>::sanitize_closure_t * = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<LangSys>
-                defaultLangSys; /* Offset to DefaultLangSys table--from
-                                 * beginning of Script table--may be Null */
-  RecordArrayOf<LangSys>
-                langSys;        /* Array of LangSysRecords--listed
-                                 * alphabetically by LangSysTag */
-  public:
-  DEFINE_SIZE_ARRAY (4, langSys);
-};
-
-typedef RecordListOf<Script> ScriptList;
-
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
-struct FeatureParamsSize
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this))) return_trace (false);
-
-    /* This subtable has some "history", if you will.  Some earlier versions of
-     * Adobe tools calculated the offset of the FeatureParams sutable from the
-     * beginning of the FeatureList table!  Now, that is dealt with in the
-     * Feature implementation.  But we still need to be able to tell junk from
-     * real data.  Note: We don't check that the nameID actually exists.
-     *
-     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
-     *
-     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
-     * coming out soon, and that the makeotf program will build a font with a
-     * 'size' feature that is correct by the specification.
-     *
-     * The specification for this feature tag is in the "OpenType Layout Tag
-     * Registry". You can see a copy of this at:
-     * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
-     *
-     * Here is one set of rules to determine if the 'size' feature is built
-     * correctly, or as by the older versions of MakeOTF. You may be able to do
-     * better.
-     *
-     * Assume that the offset to the size feature is according to specification,
-     * and make the following value checks. If it fails, assume the size
-     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
-     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
-     * offset from the beginning of the FeatureList table, rather than from the
-     * beginning of the 'size' Feature table.
-     *
-     * If "design size" == 0:
-     *     fails check
-     *
-     * Else if ("subfamily identifier" == 0 and
-     *     "range start" == 0 and
-     *     "range end" == 0 and
-     *     "range start" == 0 and
-     *     "menu name ID" == 0)
-     *     passes check: this is the format used when there is a design size
-     * specified, but there is no recommended size range.
-     *
-     * Else if ("design size" <  "range start" or
-     *     "design size" >   "range end" or
-     *     "range end" <= "range start" or
-     *     "menu name ID"  < 256 or
-     *     "menu name ID"  > 32767 or
-     *     menu name ID is not a name ID which is actually in the name table)
-     *     fails test
-     * Else
-     *     passes test.
-     */
-
-    if (!designSize)
-      return_trace (false);
-    else if (subfamilyID == 0 &&
-             subfamilyNameID == 0 &&
-             rangeStart == 0 &&
-             rangeEnd == 0)
-      return_trace (true);
-    else if (designSize < rangeStart ||
-             designSize > rangeEnd ||
-             subfamilyNameID < 256 ||
-             subfamilyNameID > 32767)
-      return_trace (false);
-    else
-      return_trace (true);
-  }
-
-  HBUINT16      designSize;     /* Represents the design size in 720/inch
-                                 * units (decipoints).  The design size entry
-                                 * must be non-zero.  When there is a design
-                                 * size but no recommended size range, the
-                                 * rest of the array will consist of zeros. */
-  HBUINT16      subfamilyID;    /* Has no independent meaning, but serves
-                                 * as an identifier that associates fonts
-                                 * in a subfamily. All fonts which share a
-                                 * Preferred or Font Family name and which
-                                 * differ only by size range shall have the
-                                 * same subfamily value, and no fonts which
-                                 * differ in weight or style shall have the
-                                 * same subfamily value. If this value is
-                                 * zero, the remaining fields in the array
-                                 * will be ignored. */
-  HBUINT16      subfamilyNameID;/* If the preceding value is non-zero, this
-                                 * value must be set in the range 256 - 32767
-                                 * (inclusive). It records the value of a
-                                 * field in the name table, which must
-                                 * contain English-language strings encoded
-                                 * in Windows Unicode and Macintosh Roman,
-                                 * and may contain additional strings
-                                 * localized to other scripts and languages.
-                                 * Each of these strings is the name an
-                                 * application should use, in combination
-                                 * with the family name, to represent the
-                                 * subfamily in a menu.  Applications will
-                                 * choose the appropriate version based on
-                                 * their selection criteria. */
-  HBUINT16      rangeStart;     /* Large end of the recommended usage range
-                                 * (inclusive), stored in 720/inch units
-                                 * (decipoints). */
-  HBUINT16      rangeEnd;       /* Small end of the recommended usage range
-                                   (exclusive), stored in 720/inch units
-                                 * (decipoints). */
-  public:
-  DEFINE_SIZE_STATIC (10);
-};
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
-struct FeatureParamsStylisticSet
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* Right now minorVersion is at zero.  Which means, any table supports
-     * the uiNameID field. */
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16      version;        /* (set to 0): This corresponds to a “minor”
-                                 * version number. Additional data may be
-                                 * added to the end of this Feature Parameters
-                                 * table in the future. */
-
-  NameID        uiNameID;       /* The 'name' table name ID that specifies a
-                                 * string (or strings, for multiple languages)
-                                 * for a user-interface label for this
-                                 * feature.  The values of uiLabelNameId and
-                                 * sampleTextNameId are expected to be in the
-                                 * font-specific name ID range (256-32767),
-                                 * though that is not a requirement in this
-                                 * Feature Parameters specification. The
-                                 * user-interface label for the feature can
-                                 * be provided in multiple languages. An
-                                 * English string should be included as a
-                                 * fallback. The string should be kept to a
-                                 * minimal length to fit comfortably with
-                                 * different application interfaces. */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
-struct FeatureParamsCharacterVariants
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  characters.sanitize (c));
-  }
-
-  HBUINT16      format;                 /* Format number is set to 0. */
-  NameID        featUILableNameID;      /* The ‘name’ table name ID that
-                                         * specifies a string (or strings,
-                                         * for multiple languages) for a
-                                         * user-interface label for this
-                                         * feature. (May be nullptr.) */
-  NameID        featUITooltipTextNameID;/* The ‘name’ table name ID that
-                                         * specifies a string (or strings,
-                                         * for multiple languages) that an
-                                         * application can use for tooltip
-                                         * text for this feature. (May be
-                                         * nullptr.) */
-  NameID        sampleTextNameID;       /* The ‘name’ table name ID that
-                                         * specifies sample text that
-                                         * illustrates the effect of this
-                                         * feature. (May be nullptr.) */
-  HBUINT16      numNamedParameters;     /* Number of named parameters. (May
-                                         * be zero.) */
-  NameID        firstParamUILabelNameID;/* The first ‘name’ table name ID
-                                         * used to specify strings for
-                                         * user-interface labels for the
-                                         * feature parameters. (Must be zero
-                                         * if numParameters is zero.) */
-  ArrayOf<HBUINT24>
-                characters;             /* Array of the Unicode Scalar Value
-                                         * of the characters for which this
-                                         * feature provides glyph variants.
-                                         * (May be zero.) */
-  public:
-  DEFINE_SIZE_ARRAY (14, characters);
-};
-
-struct FeatureParams
-{
-  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
-  {
-    TRACE_SANITIZE (this);
-    if (tag == HB_TAG ('s','i','z','e'))
-      return_trace (u.size.sanitize (c));
-    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
-      return_trace (u.stylisticSet.sanitize (c));
-    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
-      return_trace (u.characterVariants.sanitize (c));
-    return_trace (true);
-  }
-
-  inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
-  {
-    if (tag == HB_TAG ('s','i','z','e'))
-      return u.size;
-    return Null(FeatureParamsSize);
-  }
-
-  private:
-  union {
-  FeatureParamsSize                     size;
-  FeatureParamsStylisticSet             stylisticSet;
-  FeatureParamsCharacterVariants        characterVariants;
-  } u;
-  DEFINE_SIZE_STATIC (17);
-};
-
-struct Feature
-{
-  inline unsigned int get_lookup_count (void) const
-  { return lookupIndex.len; }
-  inline hb_tag_t get_lookup_index (unsigned int i) const
-  { return lookupIndex[i]; }
-  inline unsigned int get_lookup_indexes (unsigned int start_index,
-                                          unsigned int *lookup_count /* IN/OUT */,
-                                          unsigned int *lookup_tags /* OUT */) const
-  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
-
-  inline const FeatureParams &get_feature_params (void) const
-  { return this+featureParams; }
-
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<Feature>::sanitize_closure_t *closure = nullptr) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
-      return_trace (false);
-
-    /* Some earlier versions of Adobe tools calculated the offset of the
-     * FeatureParams subtable from the beginning of the FeatureList table!
-     *
-     * If sanitizing "failed" for the FeatureParams subtable, try it with the
-     * alternative location.  We would know sanitize "failed" if old value
-     * of the offset was non-zero, but it's zeroed now.
-     *
-     * Only do this for the 'size' feature, since at the time of the faulty
-     * Adobe tools, only the 'size' feature had FeatureParams defined.
-     */
-
-    OffsetTo<FeatureParams> orig_offset = featureParams;
-    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
-      return_trace (false);
-
-    if (likely (orig_offset.is_null ()))
-      return_trace (true);
-
-    if (featureParams == 0 && closure &&
-        closure->tag == HB_TAG ('s','i','z','e') &&
-        closure->list_base && closure->list_base < this)
-    {
-      unsigned int new_offset_int = (unsigned int) orig_offset -
-                                    (((char *) this) - ((char *) closure->list_base));
-
-      OffsetTo<FeatureParams> new_offset;
-      /* Check that it did not overflow. */
-      new_offset.set (new_offset_int);
-      if (new_offset == new_offset_int &&
-          c->try_set (&featureParams, new_offset) &&
-          !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
-        return_trace (false);
-
-      if (c->edit_count > 1)
-        c->edit_count--; /* This was a "legitimate" edit; don't contribute to error count. */
-    }
-
-    return_trace (true);
-  }
-
-  OffsetTo<FeatureParams>
-                 featureParams; /* Offset to Feature Parameters table (if one
-                                 * has been defined for the feature), relative
-                                 * to the beginning of the Feature Table; = Null
-                                 * if not required */
-  IndexArray     lookupIndex;   /* Array of LookupList indices */
-  public:
-  DEFINE_SIZE_ARRAY (4, lookupIndex);
-};
-
-typedef RecordListOf<Feature> FeatureList;
-
-
-struct LookupFlag : HBUINT16
-{
-  enum Flags {
-    RightToLeft         = 0x0001u,
-    IgnoreBaseGlyphs    = 0x0002u,
-    IgnoreLigatures     = 0x0004u,
-    IgnoreMarks         = 0x0008u,
-    IgnoreFlags         = 0x000Eu,
-    UseMarkFilteringSet = 0x0010u,
-    Reserved            = 0x00E0u,
-    MarkAttachmentType  = 0xFF00u
-  };
-  public:
-  DEFINE_SIZE_STATIC (2);
-};
-
-} /* namespace OT */
-/* This has to be outside the namespace. */
-HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
-namespace OT {
-
-struct Lookup
-{
-  inline unsigned int get_subtable_count (void) const { return subTable.len; }
-
-  template <typename SubTableType>
-  inline const SubTableType& get_subtable (unsigned int i) const
-  { return this+CastR<OffsetArrayOf<SubTableType> > (subTable)[i]; }
-
-  template <typename SubTableType>
-  inline const OffsetArrayOf<SubTableType>& get_subtables (void) const
-  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
-  template <typename SubTableType>
-  inline OffsetArrayOf<SubTableType>& get_subtables (void)
-  { return CastR<OffsetArrayOf<SubTableType> > (subTable); }
-
-  inline unsigned int get_type (void) const { return lookupType; }
-
-  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
-   * higher 16-bit is mark-filtering-set if the lookup uses one.
-   * Not to be confused with glyph_props which is very similar. */
-  inline uint32_t get_props (void) const
-  {
-    unsigned int flag = lookupFlag;
-    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
-    {
-      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      flag += (markFilteringSet << 16);
-    }
-    return flag;
-  }
-
-  template <typename SubTableType, typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    unsigned int lookup_type = get_type ();
-    TRACE_DISPATCH (this, lookup_type);
-    unsigned int count = get_subtable_count ();
-    for (unsigned int i = 0; i < count; i++) {
-      typename context_t::return_t r = get_subtable<SubTableType> (i).dispatch (c, lookup_type);
-      if (c->stop_sublookup_iteration (r))
-        return_trace (r);
-    }
-    return_trace (c->default_return_value ());
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         unsigned int lookup_type,
-                         uint32_t lookup_props,
-                         unsigned int num_subtables)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    lookupType.set (lookup_type);
-    lookupFlag.set (lookup_props & 0xFFFFu);
-    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
-    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-    {
-      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      markFilteringSet.set (lookup_props >> 16);
-    }
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
-    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
-    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-    {
-      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-      if (!markFilteringSet.sanitize (c)) return_trace (false);
-    }
-    return_trace (true);
-  }
-
-  private:
-  HBUINT16      lookupType;             /* Different enumerations for GSUB and GPOS */
-  HBUINT16      lookupFlag;             /* Lookup qualifiers */
-  ArrayOf<Offset16>
-                subTable;               /* Array of SubTables */
-  HBUINT16      markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets
-                                         * structure. This field is only present if bit
-                                         * UseMarkFilteringSet of lookup flags is set. */
-  public:
-  DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
-};
-
-typedef OffsetListOf<Lookup> LookupList;
-
-
-/*
- * Coverage Table
- */
-
-struct CoverageFormat1
-{
-  friend struct Coverage;
-
-  private:
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    int i = glyphArray.bsearch (glyph_id);
-    static_assert ((((unsigned int) -1) == NOT_COVERED), "");
-    return i;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    glyphArray.len.set (num_glyphs);
-    if (unlikely (!c->extend (glyphArray))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      glyphArray[i] = glyphs[i];
-    glyphs += num_glyphs;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (glyphArray.sanitize (c));
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    return glyphs->has (glyphArray[index]);
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len);
-  }
-
-  public:
-  /* Older compilers need this to be public. */
-  struct Iter {
-    inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
-    inline bool more (void) { return i < c->glyphArray.len; }
-    inline void next (void) { i++; }
-    inline hb_codepoint_t get_glyph (void) { return c->glyphArray[i]; }
-    inline unsigned int get_coverage (void) { return i; }
-
-    private:
-    const struct CoverageFormat1 *c;
-    unsigned int i;
-  };
-  private:
-
-  protected:
-  HBUINT16      coverageFormat; /* Format identifier--format = 1 */
-  SortedArrayOf<GlyphID>
-                glyphArray;     /* Array of GlyphIDs--in numerical order */
-  public:
-  DEFINE_SIZE_ARRAY (4, glyphArray);
-};
-
-struct CoverageFormat2
-{
-  friend struct Coverage;
-
-  private:
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    int i = rangeRecord.bsearch (glyph_id);
-    if (i != -1) {
-      const RangeRecord &range = rangeRecord[i];
-      return (unsigned int) range.value + (glyph_id - range.start);
-    }
-    return NOT_COVERED;
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-
-    if (unlikely (!num_glyphs))
-    {
-      rangeRecord.len.set (0);
-      return_trace (true);
-    }
-
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-        num_ranges++;
-    rangeRecord.len.set (num_ranges);
-    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
-
-    unsigned int range = 0;
-    rangeRecord[range].start = glyphs[0];
-    rangeRecord[range].value.set (0);
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i]) {
-        range++;
-        rangeRecord[range].start = glyphs[i];
-        rangeRecord[range].value.set (i);
-        rangeRecord[range].end = glyphs[i];
-      } else {
-        rangeRecord[range].end = glyphs[i];
-      }
-    glyphs += num_glyphs;
-    return_trace (true);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rangeRecord.sanitize (c));
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    unsigned int i;
-    unsigned int count = rangeRecord.len;
-    for (i = 0; i < count; i++) {
-      const RangeRecord &range = rangeRecord[i];
-      if (range.value <= index &&
-          index < (unsigned int) range.value + (range.end - range.start) &&
-          range.intersects (glyphs))
-        return true;
-      else if (index < range.value)
-        return false;
-    }
-    return false;
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-        return false;
-    return true;
-  }
-
-  public:
-  /* Older compilers need this to be public. */
-  struct Iter
-  {
-    inline void init (const CoverageFormat2 &c_)
-    {
-      c = &c_;
-      coverage = 0;
-      i = 0;
-      j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
-      if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
-      {
-        /* Broken table. Skip. */
-        i = c->rangeRecord.len;
-      }
-    }
-    inline bool more (void) { return i < c->rangeRecord.len; }
-    inline void next (void)
-    {
-      if (j >= c->rangeRecord[i].end)
-      {
-        i++;
-        if (more ())
-        {
-          hb_codepoint_t old = j;
-          j = c->rangeRecord[i].start;
-          if (unlikely (j <= old))
-          {
-            /* Broken table. Skip. Important to avoid DoS. */
-           i = c->rangeRecord.len;
-           return;
-          }
-          coverage = c->rangeRecord[i].value;
-        }
-        return;
-      }
-      coverage++;
-      j++;
-    }
-    inline hb_codepoint_t get_glyph (void) { return j; }
-    inline unsigned int get_coverage (void) { return coverage; }
-
-    private:
-    const struct CoverageFormat2 *c;
-    unsigned int i, coverage;
-    hb_codepoint_t j;
-  };
-  private:
-
-  protected:
-  HBUINT16      coverageFormat; /* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
-                rangeRecord;    /* Array of glyph ranges--ordered by
-                                 * Start GlyphID. rangeCount entries
-                                 * long */
-  public:
-  DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct Coverage
-{
-  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_coverage (glyph_id);
-    case 2: return u.format2.get_coverage (glyph_id);
-    default:return NOT_COVERED;
-    }
-  }
-
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs)
-  {
-    TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
-      if (glyphs[i - 1] + 1 != glyphs[i])
-        num_ranges++;
-    u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
-    switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs));
-    case 2: return_trace (u.format2.serialize (c, glyphs, num_glyphs));
-    default:return_trace (false);
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  inline bool intersects (const hb_set_t *glyphs) const {
-    /* TODO speed this up */
-    Coverage::Iter iter;
-    for (iter.init (*this); iter.more (); iter.next ()) {
-      if (glyphs->has (iter.get_glyph ()))
-        return true;
-    }
-    return false;
-  }
-
-  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
-    switch (u.format) {
-    case 1: return u.format1.intersects_coverage (glyphs, index);
-    case 2: return u.format2.intersects_coverage (glyphs, index);
-    default:return false;
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: return u.format1.add_coverage (glyphs);
-    case 2: return u.format2.add_coverage (glyphs);
-    default:return false;
-    }
-  }
-
-  struct Iter {
-    Iter (void) : format (0), u () {};
-    inline void init (const Coverage &c_) {
-      format = c_.u.format;
-      switch (format) {
-      case 1: u.format1.init (c_.u.format1); return;
-      case 2: u.format2.init (c_.u.format2); return;
-      default:                               return;
-      }
-    }
-    inline bool more (void) {
-      switch (format) {
-      case 1: return u.format1.more ();
-      case 2: return u.format2.more ();
-      default:return false;
-      }
-    }
-    inline void next (void) {
-      switch (format) {
-      case 1: u.format1.next (); break;
-      case 2: u.format2.next (); break;
-      default:                   break;
-      }
-    }
-    inline hb_codepoint_t get_glyph (void) {
-      switch (format) {
-      case 1: return u.format1.get_glyph ();
-      case 2: return u.format2.get_glyph ();
-      default:return 0;
-      }
-    }
-    inline unsigned int get_coverage (void) {
-      switch (format) {
-      case 1: return u.format1.get_coverage ();
-      case 2: return u.format2.get_coverage ();
-      default:return -1;
-      }
-    }
-
-    private:
-    unsigned int format;
-    union {
-    CoverageFormat2::Iter       format2; /* Put this one first since it's larger; helps shut up compiler. */
-    CoverageFormat1::Iter       format1;
-    } u;
-  };
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  CoverageFormat1       format1;
-  CoverageFormat2       format2;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Class Definition Table
- */
-
-struct ClassDefFormat1
-{
-  friend struct ClassDef;
-
-  private:
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    unsigned int i = (unsigned int) (glyph_id - startGlyph);
-    if (unlikely (i < classValue.len))
-      return classValue[i];
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && classValue.sanitize (c));
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int start = 0;
-    unsigned int count = classValue.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (classValue[i])
-        continue;
-
-      if (start != i)
-        if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
-          return false;
-
-      start = i + 1;
-    }
-    if (start != count)
-      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
-        return false;
-
-    return true;
-  }
-
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    unsigned int count = classValue.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (classValue[i] == klass)
-        glyphs->add (startGlyph + i);
-    }
-    return true;
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    unsigned int count = classValue.len;
-    if (klass == 0)
-    {
-      /* Match if there's any glyph that is not listed! */
-      hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      if (!hb_set_next (glyphs, &g))
-        return false;
-      if (g < startGlyph)
-        return true;
-      g = startGlyph + count - 1;
-      if (hb_set_next (glyphs, &g))
-        return true;
-      /* Fall through. */
-    }
-    for (unsigned int i = 0; i < count; i++)
-      if (classValue[i] == klass && glyphs->has (startGlyph + i))
-        return true;
-    return false;
-  }
-
-  protected:
-  HBUINT16      classFormat;            /* Format identifier--format = 1 */
-  GlyphID       startGlyph;             /* First GlyphID of the classValueArray */
-  ArrayOf<HBUINT16>
-                classValue;             /* Array of Class Values--one per GlyphID */
-  public:
-  DEFINE_SIZE_ARRAY (6, classValue);
-};
-
-struct ClassDefFormat2
-{
-  friend struct ClassDef;
-
-  private:
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    int i = rangeRecord.bsearch (glyph_id);
-    if (unlikely (i != -1))
-      return rangeRecord[i].value;
-    return 0;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rangeRecord.sanitize (c));
-  }
-
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (rangeRecord[i].value)
-        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-          return false;
-    return true;
-  }
-
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    unsigned int count = rangeRecord.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      if (rangeRecord[i].value == klass)
-        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
-          return false;
-    }
-    return true;
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    unsigned int count = rangeRecord.len;
-    if (klass == 0)
-    {
-      /* Match if there's any glyph that is not listed! */
-      hb_codepoint_t g = HB_SET_VALUE_INVALID;
-      for (unsigned int i = 0; i < count; i++)
-      {
-        if (!hb_set_next (glyphs, &g))
-          break;
-        if (g < rangeRecord[i].start)
-          return true;
-        g = rangeRecord[i].end;
-      }
-      if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
-        return true;
-      /* Fall through. */
-    }
-    for (unsigned int i = 0; i < count; i++)
-      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
-        return true;
-    return false;
-  }
-
-  protected:
-  HBUINT16      classFormat;    /* Format identifier--format = 2 */
-  SortedArrayOf<RangeRecord>
-                rangeRecord;    /* Array of glyph ranges--ordered by
-                                 * Start GlyphID */
-  public:
-  DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct ClassDef
-{
-  inline unsigned int get_class (hb_codepoint_t glyph_id) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_class (glyph_id);
-    case 2: return u.format2.get_class (glyph_id);
-    default:return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    case 2: return_trace (u.format2.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_coverage (set_t *glyphs) const {
-    switch (u.format) {
-    case 1: return u.format1.add_coverage (glyphs);
-    case 2: return u.format2.add_coverage (glyphs);
-    default:return false;
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename set_t>
-  inline bool add_class (set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: return u.format1.add_class (glyphs, klass);
-    case 2: return u.format2.add_class (glyphs, klass);
-    default:return false;
-    }
-  }
-
-  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
-    switch (u.format) {
-    case 1: return u.format1.intersects_class (glyphs, klass);
-    case 2: return u.format2.intersects_class (glyphs, klass);
-    default:return false;
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  ClassDefFormat1       format1;
-  ClassDefFormat2       format2;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-
-/*
- * Item Variation Store
- */
-
-struct VarRegionAxis
-{
-  inline float evaluate (int coord) const
-  {
-    int start = startCoord, peak = peakCoord, end = endCoord;
-
-    /* TODO Move these to sanitize(). */
-    if (unlikely (start > peak || peak > end))
-      return 1.;
-    if (unlikely (start < 0 && end > 0 && peak != 0))
-      return 1.;
-
-    if (peak == 0 || coord == peak)
-      return 1.;
-
-    if (coord <= start || end <= coord)
-      return 0.;
-
-    /* Interpolate */
-    if (coord < peak)
-      return float (coord - start) / (peak - start);
-    else
-      return float (end - coord) / (end - peak);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-    /* TODO Handle invalid start/peak/end configs, so we don't
-     * have to do that at runtime. */
-  }
-
-  public:
-  F2DOT14       startCoord;
-  F2DOT14       peakCoord;
-  F2DOT14       endCoord;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct VarRegionList
-{
-  inline float evaluate (unsigned int region_index,
-                         int *coords, unsigned int coord_len) const
-  {
-    if (unlikely (region_index >= regionCount))
-      return 0.;
-
-    const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
-
-    float v = 1.;
-    unsigned int count = axisCount;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      int coord = i < coord_len ? coords[i] : 0;
-      float factor = axes[i].evaluate (coord);
-      if (factor == 0.f)
-        return 0.;
-      v *= factor;
-    }
-    return v;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
-  }
-
-  protected:
-  HBUINT16      axisCount;
-  HBUINT16      regionCount;
-  UnsizedArrayOf<VarRegionAxis>
-                axesZ;
-  public:
-  DEFINE_SIZE_ARRAY (4, axesZ);
-};
-
-struct VarData
-{
-  inline unsigned int get_row_size (void) const
-  { return shortCount + regionIndices.len; }
-
-  inline unsigned int get_size (void) const
-  { return itemCount * get_row_size (); }
-
-  inline float get_delta (unsigned int inner,
-                          int *coords, unsigned int coord_count,
-                          const VarRegionList &regions) const
-  {
-    if (unlikely (inner >= itemCount))
-      return 0.;
-
-   unsigned int count = regionIndices.len;
-   unsigned int scount = shortCount;
-
-   const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
-   const HBUINT8 *row = bytes + inner * (scount + count);
-
-   float delta = 0.;
-   unsigned int i = 0;
-
-   const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
-   for (; i < scount; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
-     delta += scalar * *scursor++;
-   }
-   const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
-   for (; i < count; i++)
-   {
-     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
-     delta += scalar * *bcursor++;
-   }
-
-   return delta;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  regionIndices.sanitize(c) &&
-                  shortCount <= regionIndices.len &&
-                  c->check_array (&StructAfter<HBUINT8> (regionIndices),
-                                  get_row_size (), itemCount));
-  }
-
-  protected:
-  HBUINT16              itemCount;
-  HBUINT16              shortCount;
-  ArrayOf<HBUINT16>     regionIndices;
-  HBUINT8               bytesX[VAR];
-  public:
-  DEFINE_SIZE_ARRAY2 (6, regionIndices, bytesX);
-};
-
-struct VariationStore
-{
-  inline float get_delta (unsigned int outer, unsigned int inner,
-                          int *coords, unsigned int coord_count) const
-  {
-    if (unlikely (outer >= dataSets.len))
-      return 0.;
-
-    return (this+dataSets[outer]).get_delta (inner,
-                                             coords, coord_count,
-                                             this+regions);
-  }
-
-  inline float get_delta (unsigned int index,
-                          int *coords, unsigned int coord_count) const
-  {
-    unsigned int outer = index >> 16;
-    unsigned int inner = index & 0xFFFF;
-    return get_delta (outer, inner, coords, coord_count);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  format == 1 &&
-                  regions.sanitize (c, this) &&
-                  dataSets.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16                              format;
-  LOffsetTo<VarRegionList>              regions;
-  OffsetArrayOf<VarData, HBUINT32>      dataSets;
-  public:
-  DEFINE_SIZE_ARRAY (8, dataSets);
-};
-
-/*
- * Feature Variations
- */
-
-struct ConditionFormat1
-{
-  friend struct Condition;
-
-  private:
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
-    return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  protected:
-  HBUINT16      format;         /* Format identifier--format = 1 */
-  HBUINT16      axisIndex;
-  F2DOT14       filterRangeMinValue;
-  F2DOT14       filterRangeMaxValue;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct Condition
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.evaluate (coords, coord_len);
-    default:return false;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.format.sanitize (c)) return_trace (false);
-    switch (u.format) {
-    case 1: return_trace (u.format1.sanitize (c));
-    default:return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  ConditionFormat1      format1;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (2, format);
-};
-
-struct ConditionSet
-{
-  inline bool evaluate (const int *coords, unsigned int coord_len) const
-  {
-    unsigned int count = conditions.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
-        return false;
-    return true;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Condition, HBUINT32> conditions;
-  public:
-  DEFINE_SIZE_ARRAY (2, conditions);
-};
-
-struct FeatureTableSubstitutionRecord
-{
-  friend struct FeatureTableSubstitution;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && feature.sanitize (c, base));
-  }
-
-  protected:
-  HBUINT16              featureIndex;
-  LOffsetTo<Feature>    feature;
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct FeatureTableSubstitution
-{
-  inline const Feature *find_substitute (unsigned int feature_index) const
-  {
-    unsigned int count = substitutions.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
-      if (record.featureIndex == feature_index)
-        return &(this+record.feature);
-    }
-    return nullptr;
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  substitutions.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>        version;        /* Version--0x00010000u */
-  ArrayOf<FeatureTableSubstitutionRecord>
-                        substitutions;
-  public:
-  DEFINE_SIZE_ARRAY (6, substitutions);
-};
-
-struct FeatureVariationRecord
-{
-  friend struct FeatureVariations;
-
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (conditions.sanitize (c, base) &&
-                  substitutions.sanitize (c, base));
-  }
-
-  protected:
-  LOffsetTo<ConditionSet>
-                        conditions;
-  LOffsetTo<FeatureTableSubstitution>
-                        substitutions;
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-struct FeatureVariations
-{
-  static const unsigned int NOT_FOUND_INDEX = 0xFFFFFFFFu;
-
-  inline bool find_index (const int *coords, unsigned int coord_len,
-                          unsigned int *index) const
-  {
-    unsigned int count = varRecords.len;
-    for (unsigned int i = 0; i < count; i++)
-    {
-      const FeatureVariationRecord &record = varRecords.arrayZ[i];
-      if ((this+record.conditions).evaluate (coords, coord_len))
-      {
-        *index = i;
-        return true;
-      }
-    }
-    *index = NOT_FOUND_INDEX;
-    return false;
-  }
-
-  inline const Feature *find_substitute (unsigned int variations_index,
-                                         unsigned int feature_index) const
-  {
-    const FeatureVariationRecord &record = varRecords[variations_index];
-    return (this+record.substitutions).find_substitute (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  varRecords.sanitize (c, this));
-  }
-
-  protected:
-  FixedVersion<>        version;        /* Version--0x00010000u */
-  LArrayOf<FeatureVariationRecord>
-                        varRecords;
-  public:
-  DEFINE_SIZE_ARRAY (8, varRecords);
-};
-
-
-/*
- * Device Tables
- */
-
-struct HintingDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font) const
-  { return get_delta (font->x_ppem, font->x_scale); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font) const
-  { return get_delta (font->y_ppem, font->y_scale); }
-
-  inline unsigned int get_size (void) const
-  {
-    unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
-    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
-  }
-
-  private:
-
-  inline int get_delta (unsigned int ppem, int scale) const
-  {
-    if (!ppem) return 0;
-
-    int pixels = get_delta_pixels (ppem);
-
-    if (!pixels) return 0;
-
-    return (int) (pixels * (int64_t) scale / ppem);
-  }
-  inline int get_delta_pixels (unsigned int ppem_size) const
-  {
-    unsigned int f = deltaFormat;
-    if (unlikely (f < 1 || f > 3))
-      return 0;
-
-    if (ppem_size < startSize || ppem_size > endSize)
-      return 0;
-
-    unsigned int s = ppem_size - startSize;
-
-    unsigned int byte = deltaValue[s >> (4 - f)];
-    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
-    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
-
-    int delta = bits & mask;
-
-    if ((unsigned int) delta >= ((mask + 1) >> 1))
-      delta -= mask + 1;
-
-    return delta;
-  }
-
-  protected:
-  HBUINT16      startSize;              /* Smallest size to correct--in ppem */
-  HBUINT16      endSize;                /* Largest size to correct--in ppem */
-  HBUINT16      deltaFormat;            /* Format of DeltaValue array data: 1, 2, or 3
-                                         * 1    Signed 2-bit value, 8 values per uint16
-                                         * 2    Signed 4-bit value, 4 values per uint16
-                                         * 3    Signed 8-bit value, 2 values per uint16
-                                         */
-  HBUINT16      deltaValue[VAR];        /* Array of compressed data */
-  public:
-  DEFINE_SIZE_ARRAY (6, deltaValue);
-};
-
-struct VariationDevice
-{
-  friend struct Device;
-
-  private:
-
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_x (get_delta (font, store)); }
-
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
-  { return font->em_scalef_y (get_delta (font, store)); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  private:
-
-  inline float get_delta (hb_font_t *font, const VariationStore &store) const
-  {
-    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
-  }
-
-  protected:
-  HBUINT16      outerIndex;
-  HBUINT16      innerIndex;
-  HBUINT16      deltaFormat;    /* Format identifier for this table: 0x0x8000 */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct DeviceHeader
-{
-  protected:
-  HBUINT16              reserved1;
-  HBUINT16              reserved2;
-  public:
-  HBUINT16              format;         /* Format identifier */
-  public:
-  DEFINE_SIZE_STATIC (6);
-};
-
-struct Device
-{
-  inline hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_x_delta (font);
-    case 0x8000:
-      return u.variation.get_x_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-  inline hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null(VariationStore)) const
-  {
-    switch (u.b.format)
-    {
-    case 1: case 2: case 3:
-      return u.hinting.get_y_delta (font);
-    case 0x8000:
-      return u.variation.get_y_delta (font, store);
-    default:
-      return 0;
-    }
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!u.b.format.sanitize (c)) return_trace (false);
-    switch (u.b.format) {
-    case 1: case 2: case 3:
-      return_trace (u.hinting.sanitize (c));
-    case 0x8000:
-      return_trace (u.variation.sanitize (c));
-    default:
-      return_trace (true);
-    }
-  }
-
-  protected:
-  union {
-  DeviceHeader          b;
-  HintingDevice         hinting;
-  VariationDevice       variation;
-  } u;
-  public:
-  DEFINE_SIZE_UNION (6, b);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-common.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,2178 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2010,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_LAYOUT_COMMON_HH
+#define HB_OT_LAYOUT_COMMON_HH
+
+#include "hb.hh"
+#include "hb-ot-layout.hh"
+#include "hb-open-type.hh"
+#include "hb-set.hh"
+
+
+#ifndef HB_MAX_NESTING_LEVEL
+#define HB_MAX_NESTING_LEVEL    6
+#endif
+#ifndef HB_MAX_CONTEXT_LENGTH
+#define HB_MAX_CONTEXT_LENGTH   64
+#endif
+#ifndef HB_CLOSURE_MAX_STAGES
+/*
+ * The maximum number of times a lookup can be applied during shaping.
+ * Used to limit the number of iterations of the closure algorithm.
+ * This must be larger than the number of times add_pause() is
+ * called in a collect_features call of any shaper.
+ */
+#define HB_CLOSURE_MAX_STAGES   32
+#endif
+
+#ifndef HB_MAX_SCRIPTS
+#define HB_MAX_SCRIPTS  500
+#endif
+
+#ifndef HB_MAX_LANGSYS
+#define HB_MAX_LANGSYS  2000
+#endif
+
+
+namespace OT {
+
+
+#define NOT_COVERED             ((unsigned int) -1)
+
+
+
+/*
+ *
+ * OpenType Layout Common Table Formats
+ *
+ */
+
+
+/*
+ * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
+ */
+
+struct Record_sanitize_closure_t {
+  hb_tag_t tag;
+  const void *list_base;
+};
+
+template <typename Type>
+struct Record
+{
+  int cmp (hb_tag_t a) const { return tag.cmp (a); }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    const Record_sanitize_closure_t closure = {tag, base};
+    return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
+  }
+
+  Tag           tag;            /* 4-byte Tag identifier */
+  OffsetTo<Type>
+                offset;         /* Offset from beginning of object holding
+                                 * the Record */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+template <typename Type>
+struct RecordArrayOf : SortedArrayOf<Record<Type> >
+{
+  const OffsetTo<Type>& get_offset (unsigned int i) const
+  { return (*this)[i].offset; }
+  OffsetTo<Type>& get_offset (unsigned int i)
+  { return (*this)[i].offset; }
+  const Tag& get_tag (unsigned int i) const
+  { return (*this)[i].tag; }
+  unsigned int get_tags (unsigned int start_offset,
+                         unsigned int *record_count /* IN/OUT */,
+                         hb_tag_t     *record_tags /* OUT */) const
+  {
+    if (record_count) {
+      const Record<Type> *arr = this->sub_array (start_offset, record_count);
+      unsigned int count = *record_count;
+      for (unsigned int i = 0; i < count; i++)
+        record_tags[i] = arr[i].tag;
+    }
+    return this->len;
+  }
+  bool find_index (hb_tag_t tag, unsigned int *index) const
+  {
+    return this->bfind (tag, index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
+  }
+};
+
+template <typename Type>
+struct RecordListOf : RecordArrayOf<Type>
+{
+  const Type& operator [] (unsigned int i) const
+  { return this+this->get_offset (i); }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct RecordListOf<Type> *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    unsigned int count = this->len;
+    for (unsigned int i = 0; i < count; i++)
+      out->get_offset (i).serialize_subset (c, (*this)[i], out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (RecordArrayOf<Type>::sanitize (c, this));
+  }
+};
+
+
+struct RangeRecord
+{
+  int cmp (hb_codepoint_t g) const
+  { return g < start ? -1 : g <= end ? 0 : +1; }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  { return glyphs->intersects (start, end); }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  { return glyphs->add_range (start, end); }
+
+  GlyphID       start;          /* First GlyphID in the range */
+  GlyphID       end;            /* Last GlyphID in the range */
+  HBUINT16      value;          /* Value */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
+
+
+struct IndexArray : ArrayOf<Index>
+{
+  unsigned int get_indexes (unsigned int start_offset,
+                            unsigned int *_count /* IN/OUT */,
+                            unsigned int *_indexes /* OUT */) const
+  {
+    if (_count) {
+      const HBUINT16 *arr = this->sub_array (start_offset, _count);
+      unsigned int count = *_count;
+      for (unsigned int i = 0; i < count; i++)
+        _indexes[i] = arr[i];
+    }
+    return this->len;
+  }
+
+  void add_indexes_to (hb_set_t* output /* OUT */) const
+  {
+    output->add_array (arrayZ, len);
+  }
+};
+
+
+struct Script;
+struct LangSys;
+struct Feature;
+
+
+struct LangSys
+{
+  unsigned int get_feature_count () const
+  { return featureIndex.len; }
+  hb_tag_t get_feature_index (unsigned int i) const
+  { return featureIndex[i]; }
+  unsigned int get_feature_indexes (unsigned int start_offset,
+                                    unsigned int *feature_count /* IN/OUT */,
+                                    unsigned int *feature_indexes /* OUT */) const
+  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
+  void add_feature_indexes_to (hb_set_t *feature_indexes) const
+  { featureIndex.add_indexes_to (feature_indexes); }
+
+  bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
+  unsigned int get_required_feature_index () const
+  {
+    if (reqFeatureIndex == 0xFFFFu)
+      return Index::NOT_FOUND_INDEX;
+   return reqFeatureIndex;;
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace (c->serializer->embed (*this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t * = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
+  }
+
+  Offset16      lookupOrderZ;   /* = Null (reserved for an offset to a
+                                 * reordering table) */
+  HBUINT16      reqFeatureIndex;/* Index of a feature required for this
+                                 * language system--if no required features
+                                 * = 0xFFFFu */
+  IndexArray    featureIndex;   /* Array of indices into the FeatureList */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
+
+struct Script
+{
+  unsigned int get_lang_sys_count () const
+  { return langSys.len; }
+  const Tag& get_lang_sys_tag (unsigned int i) const
+  { return langSys.get_tag (i); }
+  unsigned int get_lang_sys_tags (unsigned int start_offset,
+                                  unsigned int *lang_sys_count /* IN/OUT */,
+                                  hb_tag_t     *lang_sys_tags /* OUT */) const
+  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
+  const LangSys& get_lang_sys (unsigned int i) const
+  {
+    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
+    return this+langSys[i].offset;
+  }
+  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+  { return langSys.find_index (tag, index); }
+
+  bool has_default_lang_sys () const           { return defaultLangSys != 0; }
+  const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Script *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    out->defaultLangSys.serialize_subset (c, this+defaultLangSys, out);
+    unsigned int count = langSys.len;
+    for (unsigned int i = 0; i < count; i++)
+      out->langSys.arrayZ[i].offset.serialize_subset (c, this+langSys[i].offset, out);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t * = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
+  }
+
+  protected:
+  OffsetTo<LangSys>
+                defaultLangSys; /* Offset to DefaultLangSys table--from
+                                 * beginning of Script table--may be Null */
+  RecordArrayOf<LangSys>
+                langSys;        /* Array of LangSysRecords--listed
+                                 * alphabetically by LangSysTag */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (4, langSys);
+};
+
+typedef RecordListOf<Script> ScriptList;
+
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
+struct FeatureParamsSize
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+
+    /* This subtable has some "history", if you will.  Some earlier versions of
+     * Adobe tools calculated the offset of the FeatureParams sutable from the
+     * beginning of the FeatureList table!  Now, that is dealt with in the
+     * Feature implementation.  But we still need to be able to tell junk from
+     * real data.  Note: We don't check that the nameID actually exists.
+     *
+     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
+     *
+     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
+     * coming out soon, and that the makeotf program will build a font with a
+     * 'size' feature that is correct by the specification.
+     *
+     * The specification for this feature tag is in the "OpenType Layout Tag
+     * Registry". You can see a copy of this at:
+     * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
+     *
+     * Here is one set of rules to determine if the 'size' feature is built
+     * correctly, or as by the older versions of MakeOTF. You may be able to do
+     * better.
+     *
+     * Assume that the offset to the size feature is according to specification,
+     * and make the following value checks. If it fails, assume the size
+     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
+     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
+     * offset from the beginning of the FeatureList table, rather than from the
+     * beginning of the 'size' Feature table.
+     *
+     * If "design size" == 0:
+     *     fails check
+     *
+     * Else if ("subfamily identifier" == 0 and
+     *     "range start" == 0 and
+     *     "range end" == 0 and
+     *     "range start" == 0 and
+     *     "menu name ID" == 0)
+     *     passes check: this is the format used when there is a design size
+     * specified, but there is no recommended size range.
+     *
+     * Else if ("design size" <  "range start" or
+     *     "design size" >   "range end" or
+     *     "range end" <= "range start" or
+     *     "menu name ID"  < 256 or
+     *     "menu name ID"  > 32767 or
+     *     menu name ID is not a name ID which is actually in the name table)
+     *     fails test
+     * Else
+     *     passes test.
+     */
+
+    if (!designSize)
+      return_trace (false);
+    else if (subfamilyID == 0 &&
+             subfamilyNameID == 0 &&
+             rangeStart == 0 &&
+             rangeEnd == 0)
+      return_trace (true);
+    else if (designSize < rangeStart ||
+             designSize > rangeEnd ||
+             subfamilyNameID < 256 ||
+             subfamilyNameID > 32767)
+      return_trace (false);
+    else
+      return_trace (true);
+  }
+
+  HBUINT16      designSize;     /* Represents the design size in 720/inch
+                                 * units (decipoints).  The design size entry
+                                 * must be non-zero.  When there is a design
+                                 * size but no recommended size range, the
+                                 * rest of the array will consist of zeros. */
+  HBUINT16      subfamilyID;    /* Has no independent meaning, but serves
+                                 * as an identifier that associates fonts
+                                 * in a subfamily. All fonts which share a
+                                 * Preferred or Font Family name and which
+                                 * differ only by size range shall have the
+                                 * same subfamily value, and no fonts which
+                                 * differ in weight or style shall have the
+                                 * same subfamily value. If this value is
+                                 * zero, the remaining fields in the array
+                                 * will be ignored. */
+  NameID        subfamilyNameID;/* If the preceding value is non-zero, this
+                                 * value must be set in the range 256 - 32767
+                                 * (inclusive). It records the value of a
+                                 * field in the name table, which must
+                                 * contain English-language strings encoded
+                                 * in Windows Unicode and Macintosh Roman,
+                                 * and may contain additional strings
+                                 * localized to other scripts and languages.
+                                 * Each of these strings is the name an
+                                 * application should use, in combination
+                                 * with the family name, to represent the
+                                 * subfamily in a menu.  Applications will
+                                 * choose the appropriate version based on
+                                 * their selection criteria. */
+  HBUINT16      rangeStart;     /* Large end of the recommended usage range
+                                 * (inclusive), stored in 720/inch units
+                                 * (decipoints). */
+  HBUINT16      rangeEnd;       /* Small end of the recommended usage range
+                                   (exclusive), stored in 720/inch units
+                                 * (decipoints). */
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
+struct FeatureParamsStylisticSet
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    /* Right now minorVersion is at zero.  Which means, any table supports
+     * the uiNameID field. */
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16      version;        /* (set to 0): This corresponds to a “minor”
+                                 * version number. Additional data may be
+                                 * added to the end of this Feature Parameters
+                                 * table in the future. */
+
+  NameID        uiNameID;       /* The 'name' table name ID that specifies a
+                                 * string (or strings, for multiple languages)
+                                 * for a user-interface label for this
+                                 * feature.  The values of uiLabelNameId and
+                                 * sampleTextNameId are expected to be in the
+                                 * font-specific name ID range (256-32767),
+                                 * though that is not a requirement in this
+                                 * Feature Parameters specification. The
+                                 * user-interface label for the feature can
+                                 * be provided in multiple languages. An
+                                 * English string should be included as a
+                                 * fallback. The string should be kept to a
+                                 * minimal length to fit comfortably with
+                                 * different application interfaces. */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
+struct FeatureParamsCharacterVariants
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  characters.sanitize (c));
+  }
+
+  HBUINT16      format;                 /* Format number is set to 0. */
+  NameID        featUILableNameID;      /* The ‘name’ table name ID that
+                                         * specifies a string (or strings,
+                                         * for multiple languages) for a
+                                         * user-interface label for this
+                                         * feature. (May be NULL.) */
+  NameID        featUITooltipTextNameID;/* The ‘name’ table name ID that
+                                         * specifies a string (or strings,
+                                         * for multiple languages) that an
+                                         * application can use for tooltip
+                                         * text for this feature. (May be
+                                         * nullptr.) */
+  NameID        sampleTextNameID;       /* The ‘name’ table name ID that
+                                         * specifies sample text that
+                                         * illustrates the effect of this
+                                         * feature. (May be NULL.) */
+  HBUINT16      numNamedParameters;     /* Number of named parameters. (May
+                                         * be zero.) */
+  NameID        firstParamUILabelNameID;/* The first ‘name’ table name ID
+                                         * used to specify strings for
+                                         * user-interface labels for the
+                                         * feature parameters. (Must be zero
+                                         * if numParameters is zero.) */
+  ArrayOf<HBUINT24>
+                characters;             /* Array of the Unicode Scalar Value
+                                         * of the characters for which this
+                                         * feature provides glyph variants.
+                                         * (May be zero.) */
+  public:
+  DEFINE_SIZE_ARRAY (14, characters);
+};
+
+struct FeatureParams
+{
+  bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
+  {
+    TRACE_SANITIZE (this);
+    if (tag == HB_TAG ('s','i','z','e'))
+      return_trace (u.size.sanitize (c));
+    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+      return_trace (u.stylisticSet.sanitize (c));
+    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+      return_trace (u.characterVariants.sanitize (c));
+    return_trace (true);
+  }
+
+  const FeatureParamsSize& get_size_params (hb_tag_t tag) const
+  {
+    if (tag == HB_TAG ('s','i','z','e'))
+      return u.size;
+    return Null (FeatureParamsSize);
+  }
+
+  const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
+  {
+    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
+      return u.stylisticSet;
+    return Null (FeatureParamsStylisticSet);
+  }
+
+  const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
+  {
+    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
+      return u.characterVariants;
+    return Null (FeatureParamsCharacterVariants);
+  }
+
+  private:
+  union {
+  FeatureParamsSize                     size;
+  FeatureParamsStylisticSet             stylisticSet;
+  FeatureParamsCharacterVariants        characterVariants;
+  } u;
+  public:
+  DEFINE_SIZE_STATIC (17);
+};
+
+struct Feature
+{
+  unsigned int get_lookup_count () const
+  { return lookupIndex.len; }
+  hb_tag_t get_lookup_index (unsigned int i) const
+  { return lookupIndex[i]; }
+  unsigned int get_lookup_indexes (unsigned int start_index,
+                                   unsigned int *lookup_count /* IN/OUT */,
+                                   unsigned int *lookup_tags /* OUT */) const
+  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
+  void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
+  { lookupIndex.add_indexes_to (lookup_indexes); }
+
+  const FeatureParams &get_feature_params () const
+  { return this+featureParams; }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Feature *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+    out->featureParams.set (0); /* TODO(subset) FeatureParams. */
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t *closure = nullptr) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
+      return_trace (false);
+
+    /* Some earlier versions of Adobe tools calculated the offset of the
+     * FeatureParams subtable from the beginning of the FeatureList table!
+     *
+     * If sanitizing "failed" for the FeatureParams subtable, try it with the
+     * alternative location.  We would know sanitize "failed" if old value
+     * of the offset was non-zero, but it's zeroed now.
+     *
+     * Only do this for the 'size' feature, since at the time of the faulty
+     * Adobe tools, only the 'size' feature had FeatureParams defined.
+     */
+
+    OffsetTo<FeatureParams> orig_offset = featureParams;
+    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
+      return_trace (false);
+
+    if (likely (orig_offset.is_null ()))
+      return_trace (true);
+
+    if (featureParams == 0 && closure &&
+        closure->tag == HB_TAG ('s','i','z','e') &&
+        closure->list_base && closure->list_base < this)
+    {
+      unsigned int new_offset_int = (unsigned int) orig_offset -
+                                    (((char *) this) - ((char *) closure->list_base));
+
+      OffsetTo<FeatureParams> new_offset;
+      /* Check that it did not overflow. */
+      new_offset.set (new_offset_int);
+      if (new_offset == new_offset_int &&
+          c->try_set (&featureParams, new_offset) &&
+          !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
+        return_trace (false);
+    }
+
+    return_trace (true);
+  }
+
+  OffsetTo<FeatureParams>
+                 featureParams; /* Offset to Feature Parameters table (if one
+                                 * has been defined for the feature), relative
+                                 * to the beginning of the Feature Table; = Null
+                                 * if not required */
+  IndexArray     lookupIndex;   /* Array of LookupList indices */
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
+};
+
+typedef RecordListOf<Feature> FeatureList;
+
+
+struct LookupFlag : HBUINT16
+{
+  enum Flags {
+    RightToLeft         = 0x0001u,
+    IgnoreBaseGlyphs    = 0x0002u,
+    IgnoreLigatures     = 0x0004u,
+    IgnoreMarks         = 0x0008u,
+    IgnoreFlags         = 0x000Eu,
+    UseMarkFilteringSet = 0x0010u,
+    Reserved            = 0x00E0u,
+    MarkAttachmentType  = 0xFF00u
+  };
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+} /* namespace OT */
+/* This has to be outside the namespace. */
+HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
+namespace OT {
+
+struct Lookup
+{
+  unsigned int get_subtable_count () const { return subTable.len; }
+
+  template <typename TSubTable>
+  const TSubTable& get_subtable (unsigned int i) const
+  { return this+CastR<OffsetArrayOf<TSubTable> > (subTable)[i]; }
+
+  template <typename TSubTable>
+  const OffsetArrayOf<TSubTable>& get_subtables () const
+  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
+  template <typename TSubTable>
+  OffsetArrayOf<TSubTable>& get_subtables ()
+  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
+
+  unsigned int get_size () const
+  {
+    const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+      return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
+    return (const char *) &markFilteringSet - (const char *) this;
+  }
+
+  unsigned int get_type () const { return lookupType; }
+
+  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
+   * higher 16-bit is mark-filtering-set if the lookup uses one.
+   * Not to be confused with glyph_props which is very similar. */
+  uint32_t get_props () const
+  {
+    unsigned int flag = lookupFlag;
+    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
+    {
+      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      flag += (markFilteringSet << 16);
+    }
+    return flag;
+  }
+
+  template <typename TSubTable, typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    unsigned int lookup_type = get_type ();
+    TRACE_DISPATCH (this, lookup_type);
+    unsigned int count = get_subtable_count ();
+    for (unsigned int i = 0; i < count; i++) {
+      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type);
+      if (c->stop_sublookup_iteration (r))
+        return_trace (r);
+    }
+    return_trace (c->default_return_value ());
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  unsigned int lookup_type,
+                  uint32_t lookup_props,
+                  unsigned int num_subtables)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+    lookupType.set (lookup_type);
+    lookupFlag.set (lookup_props & 0xFFFFu);
+    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+    {
+      if (unlikely (!c->extend (*this))) return_trace (false);
+      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      markFilteringSet.set (lookup_props >> 16);
+    }
+    return_trace (true);
+  }
+
+  /* Older compilers need this to NOT be locally defined in a function. */
+  template <typename TSubTable>
+  struct SubTableSubsetWrapper
+  {
+    SubTableSubsetWrapper (const TSubTable &subtable_,
+                           unsigned int lookup_type_) :
+                             subtable (subtable_),
+                             lookup_type (lookup_type_) {}
+
+    bool subset (hb_subset_context_t *c) const
+    { return subtable.dispatch (c, lookup_type); }
+
+    private:
+    const TSubTable &subtable;
+    unsigned int lookup_type;
+  };
+
+  template <typename TSubTable>
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct Lookup *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    /* Subset the actual subtables. */
+    /* TODO Drop empty ones, either by calling intersects() beforehand,
+     * or just dropping null offsets after. */
+    const OffsetArrayOf<TSubTable>& subtables = get_subtables<TSubTable> ();
+    OffsetArrayOf<TSubTable>& out_subtables = out->get_subtables<TSubTable> ();
+    unsigned int count = subTable.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      SubTableSubsetWrapper<TSubTable> wrapper (this+subtables[i], get_type ());
+
+      out_subtables[i].serialize_subset (c, wrapper, out);
+    }
+
+    return_trace (true);
+  }
+
+  /* Older compilers need this to NOT be locally defined in a function. */
+  template <typename TSubTable>
+  struct SubTableSanitizeWrapper : TSubTable
+  {
+    bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) const
+    { return this->dispatch (c, lookup_type); }
+  };
+
+  template <typename TSubTable>
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
+    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
+    {
+      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
+      if (!markFilteringSet.sanitize (c)) return_trace (false);
+    }
+
+    if (unlikely (!CastR<OffsetArrayOf<SubTableSanitizeWrapper<TSubTable> > > (subTable)
+                   .sanitize (c, this, get_type ())))
+      return_trace (false);
+
+    if (unlikely (get_type () == TSubTable::Extension))
+    {
+      /* The spec says all subtables of an Extension lookup should
+       * have the same type, which shall not be the Extension type
+       * itself (but we already checked for that).
+       * This is specially important if one has a reverse type! */
+      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
+      unsigned int count = get_subtable_count ();
+      for (unsigned int i = 1; i < count; i++)
+        if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
+          return_trace (false);
+    }
+    return_trace (true);
+    return_trace (true);
+  }
+
+  private:
+  HBUINT16      lookupType;             /* Different enumerations for GSUB and GPOS */
+  HBUINT16      lookupFlag;             /* Lookup qualifiers */
+  ArrayOf<Offset16>
+                subTable;               /* Array of SubTables */
+/*HBUINT16      markFilteringSetX[VAR];*//* Index (base 0) into GDEF mark glyph sets
+                                         * structure. This field is only present if bit
+                                         * UseMarkFilteringSet of lookup flags is set. */
+  public:
+  DEFINE_SIZE_ARRAY (6, subTable);
+};
+
+typedef OffsetListOf<Lookup> LookupList;
+
+
+/*
+ * Coverage Table
+ */
+
+struct CoverageFormat1
+{
+  friend struct Coverage;
+
+  private:
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    unsigned int i;
+    glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
+    return i;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (glyphArray.serialize (c, glyphs));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (glyphArray.sanitize (c));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = glyphArray.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (glyphs->has (glyphArray[i]))
+        return true;
+    return false;
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  { return glyphs->has (glyphArray[index]); }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len);
+  }
+
+  public:
+  /* Older compilers need this to be public. */
+  struct Iter {
+    void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
+    void fini () {}
+    bool more () { return i < c->glyphArray.len; }
+    void next () { i++; }
+    hb_codepoint_t get_glyph () { return c->glyphArray[i]; }
+    unsigned int get_coverage () { return i; }
+
+    private:
+    const struct CoverageFormat1 *c;
+    unsigned int i;
+  };
+  private:
+
+  protected:
+  HBUINT16      coverageFormat; /* Format identifier--format = 1 */
+  SortedArrayOf<GlyphID>
+                glyphArray;     /* Array of GlyphIDs--in numerical order */
+  public:
+  DEFINE_SIZE_ARRAY (4, glyphArray);
+};
+
+struct CoverageFormat2
+{
+  friend struct Coverage;
+
+  private:
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    const RangeRecord &range = rangeRecord.bsearch (glyph_id);
+    return likely (range.start <= range.end) ?
+           (unsigned int) range.value + (glyph_id - range.start) :
+           NOT_COVERED;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      rangeRecord.len.set (0);
+      return_trace (true);
+    }
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i])
+        num_ranges++;
+    rangeRecord.len.set (num_ranges);
+    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
+
+    unsigned int range = 0;
+    rangeRecord[range].start = glyphs[0];
+    rangeRecord[range].value.set (0);
+    for (unsigned int i = 1; i < glyphs.length; i++)
+    {
+      if (glyphs[i - 1] + 1 != glyphs[i])
+      {
+        range++;
+        rangeRecord[range].start = glyphs[i];
+        rangeRecord[range].value.set (i);
+      }
+      rangeRecord[range].end = glyphs[i];
+    }
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rangeRecord.sanitize (c));
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].intersects (glyphs))
+        return true;
+    return false;
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  {
+    unsigned int i;
+    unsigned int count = rangeRecord.len;
+    for (i = 0; i < count; i++) {
+      const RangeRecord &range = rangeRecord[i];
+      if (range.value <= index &&
+          index < (unsigned int) range.value + (range.end - range.start) &&
+          range.intersects (glyphs))
+        return true;
+      else if (index < range.value)
+        return false;
+    }
+    return false;
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+        return false;
+    return true;
+  }
+
+  public:
+  /* Older compilers need this to be public. */
+  struct Iter
+  {
+    void init (const CoverageFormat2 &c_)
+    {
+      c = &c_;
+      coverage = 0;
+      i = 0;
+      j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
+      if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
+      {
+        /* Broken table. Skip. */
+        i = c->rangeRecord.len;
+      }
+    }
+    void fini () {}
+    bool more () { return i < c->rangeRecord.len; }
+    void next ()
+    {
+      if (j >= c->rangeRecord[i].end)
+      {
+        i++;
+        if (more ())
+        {
+          hb_codepoint_t old = j;
+          j = c->rangeRecord[i].start;
+          if (unlikely (j <= old))
+          {
+            /* Broken table. Skip. Important to avoid DoS. */
+           i = c->rangeRecord.len;
+           return;
+          }
+          coverage = c->rangeRecord[i].value;
+        }
+        return;
+      }
+      coverage++;
+      j++;
+    }
+    hb_codepoint_t get_glyph () { return j; }
+    unsigned int get_coverage () { return coverage; }
+
+    private:
+    const struct CoverageFormat2 *c;
+    unsigned int i, coverage;
+    hb_codepoint_t j;
+  };
+  private:
+
+  protected:
+  HBUINT16      coverageFormat; /* Format identifier--format = 2 */
+  SortedArrayOf<RangeRecord>
+                rangeRecord;    /* Array of glyph ranges--ordered by
+                                 * Start GlyphID. rangeCount entries
+                                 * long */
+  public:
+  DEFINE_SIZE_ARRAY (4, rangeRecord);
+};
+
+struct Coverage
+{
+  unsigned int get_coverage (hb_codepoint_t glyph_id) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_coverage (glyph_id);
+    case 2: return u.format2.get_coverage (glyph_id);
+    default:return NOT_COVERED;
+    }
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i])
+        num_ranges++;
+    u.format.set (glyphs.length * 2 < num_ranges * 3 ? 1 : 2);
+
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.serialize (c, glyphs));
+    case 2: return_trace (u.format2.serialize (c, glyphs));
+    default:return_trace (false);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.intersects (glyphs);
+    case 2: return u.format2.intersects (glyphs);
+    default:return false;
+    }
+  }
+  bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.intersects_coverage (glyphs, index);
+    case 2: return u.format2.intersects_coverage (glyphs, index);
+    default:return false;
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    switch (u.format)
+    {
+    case 1: return u.format1.add_coverage (glyphs);
+    case 2: return u.format2.add_coverage (glyphs);
+    default:return false;
+    }
+  }
+
+  struct Iter
+  {
+    Iter (const Coverage &c_)
+    {
+      memset (this, 0, sizeof (*this));
+      format = c_.u.format;
+      switch (format)
+      {
+      case 1: u.format1.init (c_.u.format1); return;
+      case 2: u.format2.init (c_.u.format2); return;
+      default:                               return;
+      }
+    }
+    bool more ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.more ();
+      case 2: return u.format2.more ();
+      default:return false;
+      }
+    }
+    void next ()
+    {
+      switch (format)
+      {
+      case 1: u.format1.next (); break;
+      case 2: u.format2.next (); break;
+      default:                   break;
+      }
+    }
+    hb_codepoint_t get_glyph ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.get_glyph ();
+      case 2: return u.format2.get_glyph ();
+      default:return 0;
+      }
+    }
+    unsigned int get_coverage ()
+    {
+      switch (format)
+      {
+      case 1: return u.format1.get_coverage ();
+      case 2: return u.format2.get_coverage ();
+      default:return -1;
+      }
+    }
+
+    private:
+    unsigned int format;
+    union {
+    CoverageFormat2::Iter       format2; /* Put this one first since it's larger; helps shut up compiler. */
+    CoverageFormat1::Iter       format1;
+    } u;
+  };
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  CoverageFormat1       format1;
+  CoverageFormat2       format2;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+
+/*
+ * Class Definition Table
+ */
+
+static inline void ClassDef_serialize (hb_serialize_context_t *c,
+                                       hb_array_t<const GlyphID> glyphs,
+                                       hb_array_t<const HBUINT16> klasses);
+
+struct ClassDefFormat1
+{
+  friend struct ClassDef;
+
+  private:
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    return classValue[(unsigned int) (glyph_id - startGlyph)];
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const HBUINT16> glyphs,
+                  hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      startGlyph.set (0);
+      classValue.len.set (0);
+      return_trace (true);
+    }
+
+    hb_codepoint_t glyph_min = glyphs[0];
+    hb_codepoint_t glyph_max = glyphs[glyphs.length - 1];
+
+    startGlyph.set (glyph_min);
+    classValue.len.set (glyph_max - glyph_min + 1);
+    if (unlikely (!c->extend (classValue))) return_trace (false);
+
+    for (unsigned int i = 0; i < glyphs.length; i++)
+      classValue[glyphs[i] - glyph_min] = klasses[i];
+
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> glyphs;
+    hb_vector_t<HBUINT16> klasses;
+
+    hb_codepoint_t start = startGlyph;
+    hb_codepoint_t end   = start + classValue.len;
+    for (hb_codepoint_t g = start; g < end; g++)
+    {
+      unsigned int value = classValue[g - start];
+      if (!value) continue;
+      if (!glyphset.has (g)) continue;
+      glyphs.push()->set (glyph_map[g]);
+      klasses.push()->set (value);
+    }
+    c->serializer->propagate_error (glyphs, klasses);
+    ClassDef_serialize (c->serializer, glyphs, klasses);
+    return_trace (glyphs.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && classValue.sanitize (c));
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int start = 0;
+    unsigned int count = classValue.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (classValue[i])
+        continue;
+
+      if (start != i)
+        if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
+          return false;
+
+      start = i + 1;
+    }
+    if (start != count)
+      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
+        return false;
+
+    return true;
+  }
+
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = classValue.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (classValue[i] == klass) glyphs->add (startGlyph + i);
+    return true;
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next()? */
+    hb_codepoint_t start = startGlyph;
+    hb_codepoint_t end = startGlyph + classValue.len;
+    for (hb_codepoint_t iter = startGlyph - 1;
+         hb_set_next (glyphs, &iter) && iter < end;)
+      if (classValue[iter - start]) return true;
+    return false;
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = classValue.len;
+    if (klass == 0)
+    {
+      /* Match if there's any glyph that is not listed! */
+      hb_codepoint_t g = HB_SET_VALUE_INVALID;
+      if (!hb_set_next (glyphs, &g)) return false;
+      if (g < startGlyph) return true;
+      g = startGlyph + count - 1;
+      if (hb_set_next (glyphs, &g)) return true;
+      /* Fall through. */
+    }
+    for (unsigned int i = 0; i < count; i++)
+      if (classValue[i] == klass && glyphs->has (startGlyph + i))
+        return true;
+    return false;
+  }
+
+  protected:
+  HBUINT16      classFormat;    /* Format identifier--format = 1 */
+  GlyphID       startGlyph;     /* First GlyphID of the classValueArray */
+  ArrayOf<HBUINT16>
+                classValue;     /* Array of Class Values--one per GlyphID */
+  public:
+  DEFINE_SIZE_ARRAY (6, classValue);
+};
+
+struct ClassDefFormat2
+{
+  friend struct ClassDef;
+
+  private:
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    return rangeRecord.bsearch (glyph_id).value;
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const HBUINT16> glyphs,
+                  hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    if (unlikely (!glyphs.length))
+    {
+      rangeRecord.len.set (0);
+      return_trace (true);
+    }
+
+    unsigned int num_ranges = 1;
+    for (unsigned int i = 1; i < glyphs.length; i++)
+      if (glyphs[i - 1] + 1 != glyphs[i] ||
+          klasses[i - 1] != klasses[i])
+        num_ranges++;
+    rangeRecord.len.set (num_ranges);
+    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
+
+    unsigned int range = 0;
+    rangeRecord[range].start = glyphs[0];
+    rangeRecord[range].value.set (klasses[0]);
+    for (unsigned int i = 1; i < glyphs.length; i++)
+    {
+      if (glyphs[i - 1] + 1 != glyphs[i] ||
+          klasses[i - 1] != klasses[i])
+      {
+        range++;
+        rangeRecord[range].start = glyphs[i];
+        rangeRecord[range].value = klasses[i];
+      }
+      rangeRecord[range].end = glyphs[i];
+    }
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> glyphs;
+    hb_vector_t<HBUINT16> klasses;
+
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      unsigned int value = rangeRecord[i].value;
+      if (!value) continue;
+      hb_codepoint_t start = rangeRecord[i].start;
+      hb_codepoint_t end   = rangeRecord[i].end + 1;
+      for (hb_codepoint_t g = start; g < end; g++)
+      {
+        if (!glyphset.has (g)) continue;
+        glyphs.push ()->set (glyph_map[g]);
+        klasses.push ()->set (value);
+      }
+    }
+    c->serializer->propagate_error (glyphs, klasses);
+    ClassDef_serialize (c->serializer, glyphs, klasses);
+    return_trace (glyphs.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rangeRecord.sanitize (c));
+  }
+
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].value)
+        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+          return false;
+    return true;
+  }
+
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (rangeRecord[i].value == klass)
+        if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
+          return false;
+    }
+    return true;
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    /* TODO Speed up, using hb_set_next() and bsearch()? */
+    unsigned int count = rangeRecord.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].intersects (glyphs))
+        return true;
+    return false;
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    unsigned int count = rangeRecord.len;
+    if (klass == 0)
+    {
+      /* Match if there's any glyph that is not listed! */
+      hb_codepoint_t g = HB_SET_VALUE_INVALID;
+      for (unsigned int i = 0; i < count; i++)
+      {
+        if (!hb_set_next (glyphs, &g))
+          break;
+        if (g < rangeRecord[i].start)
+          return true;
+        g = rangeRecord[i].end;
+      }
+      if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
+        return true;
+      /* Fall through. */
+    }
+    for (unsigned int i = 0; i < count; i++)
+      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
+        return true;
+    return false;
+  }
+
+  protected:
+  HBUINT16      classFormat;    /* Format identifier--format = 2 */
+  SortedArrayOf<RangeRecord>
+                rangeRecord;    /* Array of glyph ranges--ordered by
+                                 * Start GlyphID */
+  public:
+  DEFINE_SIZE_ARRAY (4, rangeRecord);
+};
+
+struct ClassDef
+{
+  unsigned int get_class (hb_codepoint_t glyph_id) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_class (glyph_id);
+    case 2: return u.format2.get_class (glyph_id);
+    default:return 0;
+    }
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const HBUINT16> klasses)
+  {
+    TRACE_SERIALIZE (this);
+    if (unlikely (!c->extend_min (*this))) return_trace (false);
+
+    unsigned int format = 2;
+    if (glyphs.length)
+    {
+      hb_codepoint_t glyph_min = glyphs[0];
+      hb_codepoint_t glyph_max = glyphs[glyphs.length - 1];
+
+      unsigned int num_ranges = 1;
+      for (unsigned int i = 1; i < glyphs.length; i++)
+        if (glyphs[i - 1] + 1 != glyphs[i] ||
+            klasses[i - 1] != klasses[i])
+          num_ranges++;
+
+      if (1 + (glyph_max - glyph_min + 1) < num_ranges * 3)
+        format = 1;
+    }
+    u.format.set (format);
+
+    switch (u.format)
+    {
+    case 1: return_trace (u.format1.serialize (c, glyphs, klasses));
+    case 2: return_trace (u.format2.serialize (c, glyphs, klasses));
+    default:return_trace (false);
+    }
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    switch (u.format) {
+    case 1: return_trace (u.format1.subset (c));
+    case 2: return_trace (u.format2.subset (c));
+    default:return_trace (false);
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_coverage (set_t *glyphs) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.add_coverage (glyphs);
+    case 2: return u.format2.add_coverage (glyphs);
+    default:return false;
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename set_t>
+  bool add_class (set_t *glyphs, unsigned int klass) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.add_class (glyphs, klass);
+    case 2: return u.format2.add_class (glyphs, klass);
+    default:return false;
+    }
+  }
+
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.intersects (glyphs);
+    case 2: return u.format2.intersects (glyphs);
+    default:return false;
+    }
+  }
+  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.intersects_class (glyphs, klass);
+    case 2: return u.format2.intersects_class (glyphs, klass);
+    default:return false;
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  ClassDefFormat1       format1;
+  ClassDefFormat2       format2;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+static inline void ClassDef_serialize (hb_serialize_context_t *c,
+                                       hb_array_t<const GlyphID> glyphs,
+                                       hb_array_t<const HBUINT16> klasses)
+{ c->start_embed<ClassDef> ()->serialize (c, glyphs, klasses); }
+
+
+/*
+ * Item Variation Store
+ */
+
+struct VarRegionAxis
+{
+  float evaluate (int coord) const
+  {
+    int start = startCoord, peak = peakCoord, end = endCoord;
+
+    /* TODO Move these to sanitize(). */
+    if (unlikely (start > peak || peak > end))
+      return 1.;
+    if (unlikely (start < 0 && end > 0 && peak != 0))
+      return 1.;
+
+    if (peak == 0 || coord == peak)
+      return 1.;
+
+    if (coord <= start || end <= coord)
+      return 0.;
+
+    /* Interpolate */
+    if (coord < peak)
+      return float (coord - start) / (peak - start);
+    else
+      return float (end - coord) / (end - peak);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+    /* TODO Handle invalid start/peak/end configs, so we don't
+     * have to do that at runtime. */
+  }
+
+  public:
+  F2DOT14       startCoord;
+  F2DOT14       peakCoord;
+  F2DOT14       endCoord;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct VarRegionList
+{
+  float evaluate (unsigned int region_index,
+                         const int *coords, unsigned int coord_len) const
+  {
+    if (unlikely (region_index >= regionCount))
+      return 0.;
+
+    const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
+
+    float v = 1.;
+    unsigned int count = axisCount;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      int coord = i < coord_len ? coords[i] : 0;
+      float factor = axes[i].evaluate (coord);
+      if (factor == 0.f)
+        return 0.;
+      v *= factor;
+    }
+    return v;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
+  }
+
+  unsigned int get_region_count () const { return regionCount; }
+
+  protected:
+  HBUINT16      axisCount;
+  HBUINT16      regionCount;
+  UnsizedArrayOf<VarRegionAxis>
+                axesZ;
+  public:
+  DEFINE_SIZE_ARRAY (4, axesZ);
+};
+
+struct VarData
+{
+  unsigned int get_region_index_count () const
+  { return regionIndices.len; }
+
+  unsigned int get_row_size () const
+  { return shortCount + regionIndices.len; }
+
+  unsigned int get_size () const
+  { return itemCount * get_row_size (); }
+
+  float get_delta (unsigned int inner,
+                          const int *coords, unsigned int coord_count,
+                          const VarRegionList &regions) const
+  {
+    if (unlikely (inner >= itemCount))
+      return 0.;
+
+   unsigned int count = regionIndices.len;
+   unsigned int scount = shortCount;
+
+   const HBUINT8 *bytes = &StructAfter<HBUINT8> (regionIndices);
+   const HBUINT8 *row = bytes + inner * (scount + count);
+
+   float delta = 0.;
+   unsigned int i = 0;
+
+   const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
+   for (; i < scount; i++)
+   {
+     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+     delta += scalar * *scursor++;
+   }
+   const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
+   for (; i < count; i++)
+   {
+     float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+     delta += scalar * *bcursor++;
+   }
+
+   return delta;
+  }
+
+  void get_scalars (int *coords, unsigned int coord_count,
+                    const VarRegionList &regions,
+                    float *scalars /*OUT */,
+                    unsigned int num_scalars) const
+  {
+    assert (num_scalars == regionIndices.len);
+   for (unsigned int i = 0; i < num_scalars; i++)
+   {
+     scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+   }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  regionIndices.sanitize (c) &&
+                  shortCount <= regionIndices.len &&
+                  c->check_range (&StructAfter<HBUINT8> (regionIndices),
+                                  itemCount,
+                                  get_row_size ()));
+  }
+
+  protected:
+  HBUINT16              itemCount;
+  HBUINT16              shortCount;
+  ArrayOf<HBUINT16>     regionIndices;
+/*UnsizedArrayOf<HBUINT8>bytesX;*/
+  public:
+  DEFINE_SIZE_ARRAY (6, regionIndices);
+};
+
+struct VariationStore
+{
+  float get_delta (unsigned int outer, unsigned int inner,
+                   const int *coords, unsigned int coord_count) const
+  {
+    if (unlikely (outer >= dataSets.len))
+      return 0.;
+
+    return (this+dataSets[outer]).get_delta (inner,
+                                             coords, coord_count,
+                                             this+regions);
+  }
+
+  float get_delta (unsigned int index,
+                   const int *coords, unsigned int coord_count) const
+  {
+    unsigned int outer = index >> 16;
+    unsigned int inner = index & 0xFFFF;
+    return get_delta (outer, inner, coords, coord_count);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  format == 1 &&
+                  regions.sanitize (c, this) &&
+                  dataSets.sanitize (c, this));
+  }
+
+  unsigned int get_region_index_count (unsigned int ivs) const
+  { return (this+dataSets[ivs]).get_region_index_count (); }
+
+  void get_scalars (unsigned int ivs,
+                    int *coords, unsigned int coord_count,
+                    float *scalars /*OUT*/,
+                    unsigned int num_scalars) const
+  {
+    (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
+                                      &scalars[0], num_scalars);
+  }
+
+  protected:
+  HBUINT16                              format;
+  LOffsetTo<VarRegionList>              regions;
+  LOffsetArrayOf<VarData>               dataSets;
+  public:
+  DEFINE_SIZE_ARRAY (8, dataSets);
+};
+
+/*
+ * Feature Variations
+ */
+
+struct ConditionFormat1
+{
+  friend struct Condition;
+
+  private:
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
+    return filterRangeMinValue <= coord && coord <= filterRangeMaxValue;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier--format = 1 */
+  HBUINT16      axisIndex;
+  F2DOT14       filterRangeMinValue;
+  F2DOT14       filterRangeMaxValue;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct Condition
+{
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    switch (u.format) {
+    case 1: return u.format1.evaluate (coords, coord_len);
+    default:return false;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.format.sanitize (c)) return_trace (false);
+    switch (u.format) {
+    case 1: return_trace (u.format1.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  ConditionFormat1      format1;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+struct ConditionSet
+{
+  bool evaluate (const int *coords, unsigned int coord_len) const
+  {
+    unsigned int count = conditions.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len))
+        return false;
+    return true;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, this));
+  }
+
+  protected:
+  LOffsetArrayOf<Condition>     conditions;
+  public:
+  DEFINE_SIZE_ARRAY (2, conditions);
+};
+
+struct FeatureTableSubstitutionRecord
+{
+  friend struct FeatureTableSubstitution;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && feature.sanitize (c, base));
+  }
+
+  protected:
+  HBUINT16              featureIndex;
+  LOffsetTo<Feature>    feature;
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct FeatureTableSubstitution
+{
+  const Feature *find_substitute (unsigned int feature_index) const
+  {
+    unsigned int count = substitutions.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
+      if (record.featureIndex == feature_index)
+        return &(this+record.feature);
+    }
+    return nullptr;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  substitutions.sanitize (c, this));
+  }
+
+  protected:
+  FixedVersion<>        version;        /* Version--0x00010000u */
+  ArrayOf<FeatureTableSubstitutionRecord>
+                        substitutions;
+  public:
+  DEFINE_SIZE_ARRAY (6, substitutions);
+};
+
+struct FeatureVariationRecord
+{
+  friend struct FeatureVariations;
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (conditions.sanitize (c, base) &&
+                  substitutions.sanitize (c, base));
+  }
+
+  protected:
+  LOffsetTo<ConditionSet>
+                        conditions;
+  LOffsetTo<FeatureTableSubstitution>
+                        substitutions;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct FeatureVariations
+{
+  static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
+
+  bool find_index (const int *coords, unsigned int coord_len,
+                          unsigned int *index) const
+  {
+    unsigned int count = varRecords.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      const FeatureVariationRecord &record = varRecords.arrayZ[i];
+      if ((this+record.conditions).evaluate (coords, coord_len))
+      {
+        *index = i;
+        return true;
+      }
+    }
+    *index = NOT_FOUND_INDEX;
+    return false;
+  }
+
+  const Feature *find_substitute (unsigned int variations_index,
+                                  unsigned int feature_index) const
+  {
+    const FeatureVariationRecord &record = varRecords[variations_index];
+    return (this+record.substitutions).find_substitute (feature_index);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace (c->serializer->embed (*this));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  varRecords.sanitize (c, this));
+  }
+
+  protected:
+  FixedVersion<>        version;        /* Version--0x00010000u */
+  LArrayOf<FeatureVariationRecord>
+                        varRecords;
+  public:
+  DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
+};
+
+
+/*
+ * Device Tables
+ */
+
+struct HintingDevice
+{
+  friend struct Device;
+
+  private:
+
+  hb_position_t get_x_delta (hb_font_t *font) const
+  { return get_delta (font->x_ppem, font->x_scale); }
+
+  hb_position_t get_y_delta (hb_font_t *font) const
+  { return get_delta (font->y_ppem, font->y_scale); }
+
+  unsigned int get_size () const
+  {
+    unsigned int f = deltaFormat;
+    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
+    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
+  }
+
+  private:
+
+  int get_delta (unsigned int ppem, int scale) const
+  {
+    if (!ppem) return 0;
+
+    int pixels = get_delta_pixels (ppem);
+
+    if (!pixels) return 0;
+
+    return (int) (pixels * (int64_t) scale / ppem);
+  }
+  int get_delta_pixels (unsigned int ppem_size) const
+  {
+    unsigned int f = deltaFormat;
+    if (unlikely (f < 1 || f > 3))
+      return 0;
+
+    if (ppem_size < startSize || ppem_size > endSize)
+      return 0;
+
+    unsigned int s = ppem_size - startSize;
+
+    unsigned int byte = deltaValueZ[s >> (4 - f)];
+    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
+    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
+
+    int delta = bits & mask;
+
+    if ((unsigned int) delta >= ((mask + 1) >> 1))
+      delta -= mask + 1;
+
+    return delta;
+  }
+
+  protected:
+  HBUINT16      startSize;              /* Smallest size to correct--in ppem */
+  HBUINT16      endSize;                /* Largest size to correct--in ppem */
+  HBUINT16      deltaFormat;            /* Format of DeltaValue array data: 1, 2, or 3
+                                         * 1    Signed 2-bit value, 8 values per uint16
+                                         * 2    Signed 4-bit value, 4 values per uint16
+                                         * 3    Signed 8-bit value, 2 values per uint16
+                                         */
+  UnsizedArrayOf<HBUINT16>
+                deltaValueZ;            /* Array of compressed data */
+  public:
+  DEFINE_SIZE_ARRAY (6, deltaValueZ);
+};
+
+struct VariationDevice
+{
+  friend struct Device;
+
+  private:
+
+  hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
+  { return font->em_scalef_x (get_delta (font, store)); }
+
+  hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
+  { return font->em_scalef_y (get_delta (font, store)); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  private:
+
+  float get_delta (hb_font_t *font, const VariationStore &store) const
+  {
+    return store.get_delta (outerIndex, innerIndex, font->coords, font->num_coords);
+  }
+
+  protected:
+  HBUINT16      outerIndex;
+  HBUINT16      innerIndex;
+  HBUINT16      deltaFormat;    /* Format identifier for this table: 0x0x8000 */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct DeviceHeader
+{
+  protected:
+  HBUINT16              reserved1;
+  HBUINT16              reserved2;
+  public:
+  HBUINT16              format;         /* Format identifier */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct Device
+{
+  hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+  {
+    switch (u.b.format)
+    {
+    case 1: case 2: case 3:
+      return u.hinting.get_x_delta (font);
+    case 0x8000:
+      return u.variation.get_x_delta (font, store);
+    default:
+      return 0;
+    }
+  }
+  hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+  {
+    switch (u.b.format)
+    {
+    case 1: case 2: case 3:
+      return u.hinting.get_y_delta (font);
+    case 0x8000:
+      return u.variation.get_y_delta (font, store);
+    default:
+      return 0;
+    }
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.b.format.sanitize (c)) return_trace (false);
+    switch (u.b.format) {
+    case 1: case 2: case 3:
+      return_trace (u.hinting.sanitize (c));
+    case 0x8000:
+      return_trace (u.variation.sanitize (c));
+    default:
+      return_trace (true);
+    }
+  }
+
+  protected:
+  union {
+  DeviceHeader          b;
+  HintingDevice         hinting;
+  VariationDevice       variation;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (6, b);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_LAYOUT_COMMON_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gdef-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gdef-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,9 +29,9 @@
 #ifndef HB_OT_LAYOUT_GDEF_TABLE_HH
 #define HB_OT_LAYOUT_GDEF_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
-#include "hb-font-private.hh"
+#include "hb-font.hh"
 
 
 namespace OT {
@@ -46,10 +46,10 @@
 
 struct AttachList
 {
-  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
-                                         unsigned int start_offset,
-                                         unsigned int *point_count /* IN/OUT */,
-                                         unsigned int *point_array /* OUT */) const
+  unsigned int get_attach_points (hb_codepoint_t glyph_id,
+                                  unsigned int start_offset,
+                                  unsigned int *point_count /* IN/OUT */,
+                                  unsigned int *point_array /* OUT */) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph_id);
     if (index == NOT_COVERED)
@@ -61,9 +61,10 @@
 
     const AttachPoint &points = this+attachPoint[index];
 
-    if (point_count) {
-      const HBUINT16 *array = points.sub_array (start_offset, point_count);
-      unsigned int count = *point_count;
+    if (point_count)
+    {
+      hb_array_t<const HBUINT16> array = points.sub_array (start_offset, point_count);
+      unsigned int count = array.length;
       for (unsigned int i = 0; i < count; i++)
         point_array[i] = array[i];
     }
@@ -71,7 +72,7 @@
     return points.len;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && attachPoint.sanitize (c, this));
@@ -97,12 +98,12 @@
   friend struct CaretValue;
 
   private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -120,16 +121,14 @@
   friend struct CaretValue;
 
   private:
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     hb_position_t x, y;
-    if (font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y))
-      return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
-    else
-      return 0;
+    font->get_glyph_contour_point_for_origin (glyph_id, caretValuePoint, direction, &x, &y);
+    return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -146,14 +145,15 @@
 {
   friend struct CaretValue;
 
-  inline hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction, const VariationStore &var_store) const
+  hb_position_t get_caret_value (hb_font_t *font, hb_direction_t direction,
+                                 const VariationStore &var_store) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
            font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font, var_store) :
            font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font, var_store);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
@@ -172,7 +172,7 @@
 
 struct CaretValue
 {
-  inline hb_position_t get_caret_value (hb_font_t *font,
+  hb_position_t get_caret_value (hb_font_t *font,
                                         hb_direction_t direction,
                                         hb_codepoint_t glyph_id,
                                         const VariationStore &var_store) const
@@ -185,7 +185,7 @@
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -210,17 +210,18 @@
 
 struct LigGlyph
 {
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                      hb_direction_t direction,
-                                      hb_codepoint_t glyph_id,
-                                      const VariationStore &var_store,
-                                      unsigned int start_offset,
-                                      unsigned int *caret_count /* IN/OUT */,
-                                      hb_position_t *caret_array /* OUT */) const
+  unsigned int get_lig_carets (hb_font_t *font,
+                               hb_direction_t direction,
+                               hb_codepoint_t glyph_id,
+                               const VariationStore &var_store,
+                               unsigned int start_offset,
+                               unsigned int *caret_count /* IN/OUT */,
+                               hb_position_t *caret_array /* OUT */) const
   {
-    if (caret_count) {
-      const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
-      unsigned int count = *caret_count;
+    if (caret_count)
+    {
+      hb_array_t <const OffsetTo<CaretValue> > array = carets.sub_array (start_offset, caret_count);
+      unsigned int count = array.length;
       for (unsigned int i = 0; i < count; i++)
         caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
     }
@@ -228,7 +229,7 @@
     return carets.len;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (carets.sanitize (c, this));
@@ -245,13 +246,13 @@
 
 struct LigCaretList
 {
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                      hb_direction_t direction,
-                                      hb_codepoint_t glyph_id,
-                                      const VariationStore &var_store,
-                                      unsigned int start_offset,
-                                      unsigned int *caret_count /* IN/OUT */,
-                                      hb_position_t *caret_array /* OUT */) const
+  unsigned int get_lig_carets (hb_font_t *font,
+                               hb_direction_t direction,
+                               hb_codepoint_t glyph_id,
+                               const VariationStore &var_store,
+                               unsigned int start_offset,
+                               unsigned int *caret_count /* IN/OUT */,
+                               hb_position_t *caret_array /* OUT */) const
   {
     unsigned int index = (this+coverage).get_coverage (glyph_id);
     if (index == NOT_COVERED)
@@ -264,7 +265,7 @@
     return lig_glyph.get_lig_carets (font, direction, glyph_id, var_store, start_offset, caret_count, caret_array);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ligGlyph.sanitize (c, this));
@@ -284,10 +285,10 @@
 
 struct MarkGlyphSetsFormat1
 {
-  inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return (this+coverage[set_index]).get_coverage (glyph_id) != NOT_COVERED; }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this));
@@ -304,7 +305,7 @@
 
 struct MarkGlyphSets
 {
-  inline bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   {
     switch (u.format) {
     case 1: return u.format1.covers (set_index, glyph_id);
@@ -312,7 +313,7 @@
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -337,9 +338,10 @@
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gdef
  */
 
+
 struct GDEF
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_GDEF;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
 
   enum GlyphClasses {
     UnclassifiedGlyph   = 0,
@@ -349,59 +351,47 @@
     ComponentGlyph      = 4
   };
 
-  inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
-  inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
+  bool has_data () const { return version.to_int (); }
+  bool has_glyph_classes () const { return glyphClassDef != 0; }
+  unsigned int get_glyph_class (hb_codepoint_t glyph) const
   { return (this+glyphClassDef).get_class (glyph); }
-  inline void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
+  void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
   { (this+glyphClassDef).add_class (glyphs, klass); }
 
-  inline bool has_mark_attachment_types (void) const { return markAttachClassDef != 0; }
-  inline unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
+  bool has_mark_attachment_types () const { return markAttachClassDef != 0; }
+  unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
   { return (this+markAttachClassDef).get_class (glyph); }
 
-  inline bool has_attach_points (void) const { return attachList != 0; }
-  inline unsigned int get_attach_points (hb_codepoint_t glyph_id,
-                                         unsigned int start_offset,
-                                         unsigned int *point_count /* IN/OUT */,
-                                         unsigned int *point_array /* OUT */) const
+  bool has_attach_points () const { return attachList != 0; }
+  unsigned int get_attach_points (hb_codepoint_t glyph_id,
+                                  unsigned int start_offset,
+                                  unsigned int *point_count /* IN/OUT */,
+                                  unsigned int *point_array /* OUT */) const
   { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
 
-  inline bool has_lig_carets (void) const { return ligCaretList != 0; }
-  inline unsigned int get_lig_carets (hb_font_t *font,
-                                      hb_direction_t direction,
-                                      hb_codepoint_t glyph_id,
-                                      unsigned int start_offset,
-                                      unsigned int *caret_count /* IN/OUT */,
-                                      hb_position_t *caret_array /* OUT */) const
+  bool has_lig_carets () const { return ligCaretList != 0; }
+  unsigned int get_lig_carets (hb_font_t *font,
+                               hb_direction_t direction,
+                               hb_codepoint_t glyph_id,
+                               unsigned int start_offset,
+                               unsigned int *caret_count /* IN/OUT */,
+                               hb_position_t *caret_array /* OUT */) const
   { return (this+ligCaretList).get_lig_carets (font,
                                                direction, glyph_id, get_var_store(),
                                                start_offset, caret_count, caret_array); }
 
-  inline bool has_mark_sets (void) const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
-  inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
+  bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
+  bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
   { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
 
-  inline bool has_var_store (void) const { return version.to_int () >= 0x00010003u && varStore != 0; }
-  inline const VariationStore &get_var_store (void) const
+  bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; }
+  const VariationStore &get_var_store () const
   { return version.to_int () >= 0x00010003u ? this+varStore : Null(VariationStore); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  glyphClassDef.sanitize (c, this) &&
-                  attachList.sanitize (c, this) &&
-                  ligCaretList.sanitize (c, this) &&
-                  markAttachClassDef.sanitize (c, this) &&
-                  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
-                  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
-  }
-
   /* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
-   * glyph class and other bits, and high 8-bit gthe mark attachment type (if any).
+   * glyph class and other bits, and high 8-bit the mark attachment type (if any).
    * Not to be confused with lookup_props which is very similar. */
-  inline unsigned int get_glyph_props (hb_codepoint_t glyph) const
+  unsigned int get_glyph_props (hb_codepoint_t glyph) const
   {
     unsigned int klass = get_glyph_class (glyph);
 
@@ -419,6 +409,65 @@
     }
   }
 
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                   hb_face_t *face) const;
+
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<GDEF> (face);
+      if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
+      {
+        hb_blob_destroy (this->table.get_blob ());
+        this->table = hb_blob_get_empty ();
+      }
+    }
+
+    void fini () { this->table.destroy (); }
+
+    hb_blob_ptr_t<GDEF> table;
+  };
+
+  unsigned int get_size () const
+  {
+    return min_size +
+           (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
+           (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct GDEF *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    out->glyphClassDef.serialize_subset (c, this+glyphClassDef, out);
+    out->attachList.set (0);//TODO(subset) serialize_subset (c, this+attachList, out);
+    out->ligCaretList.set (0);//TODO(subset) serialize_subset (c, this+ligCaretList, out);
+    out->markAttachClassDef.serialize_subset (c, this+markAttachClassDef, out);
+
+    if (version.to_int () >= 0x00010002u)
+      out->markGlyphSetsDef.set (0);// TODO(subset) serialize_subset (c, this+markGlyphSetsDef, out);
+
+    if (version.to_int () >= 0x00010003u)
+      out->varStore.set (0);// TODO(subset) serialize_subset (c, this+varStore, out);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  glyphClassDef.sanitize (c, this) &&
+                  attachList.sanitize (c, this) &&
+                  ligCaretList.sanitize (c, this) &&
+                  markAttachClassDef.sanitize (c, this) &&
+                  (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
+                  (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
+  }
 
   protected:
   FixedVersion<>version;                /* Version of the GDEF table--currently
@@ -453,6 +502,7 @@
   DEFINE_SIZE_MIN (12);
 };
 
+struct GDEF_accelerator_t : GDEF::accelerator_t {};
 
 } /* namespace OT */
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gpos-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gpos-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,7 +29,7 @@
 #ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
 #define HB_OT_LAYOUT_GPOS_TABLE_HH
 
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-layout-gsubgpos.hh"
 
 
 namespace OT {
@@ -53,7 +53,7 @@
 
 typedef HBUINT16 Value;
 
-typedef Value ValueRecord[VAR];
+typedef UnsizedArrayOf<Value> ValueRecord;
 
 struct ValueFormat : HBUINT16
 {
@@ -84,79 +84,79 @@
   HBINT16               yAdvance;               /* Vertical adjustment for advance--in
                                          * design units (only used for vertical
                                          * writing) */
-  Offset        xPlaDevice;             /* Offset to Device table for
+  OffsetTo<Device>      xPlaDevice;     /* Offset to Device table for
                                          * horizontal placement--measured from
                                          * beginning of PosTable (may be NULL) */
-  Offset        yPlaDevice;             /* Offset to Device table for vertical
+  OffsetTo<Device>      yPlaDevice;     /* Offset to Device table for vertical
                                          * placement--measured from beginning
                                          * of PosTable (may be NULL) */
-  Offset        xAdvDevice;             /* Offset to Device table for
+  OffsetTo<Device>      xAdvDevice;     /* Offset to Device table for
                                          * horizontal advance--measured from
                                          * beginning of PosTable (may be NULL) */
-  Offset        yAdvDevice;             /* Offset to Device table for vertical
+  OffsetTo<Device>      yAdvDevice;     /* Offset to Device table for vertical
                                          * advance--measured from beginning of
                                          * PosTable (may be NULL) */
 #endif
 
-  inline unsigned int get_len (void) const
-  { return _hb_popcount ((unsigned int) *this); }
-  inline unsigned int get_size (void) const
-  { return get_len () * Value::static_size; }
+  unsigned int get_len () const  { return hb_popcount ((unsigned int) *this); }
+  unsigned int get_size () const { return get_len () * Value::static_size; }
 
-  void apply_value (hb_ot_apply_context_t   *c,
+  bool apply_value (hb_ot_apply_context_t   *c,
                     const void           *base,
                     const Value          *values,
                     hb_glyph_position_t  &glyph_pos) const
   {
+    bool ret = false;
     unsigned int format = *this;
-    if (!format) return;
+    if (!format) return ret;
 
     hb_font_t *font = c->font;
-    hb_bool_t horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
+    bool horizontal = HB_DIRECTION_IS_HORIZONTAL (c->direction);
 
-    if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++));
-    if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++));
+    if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++, &ret));
+    if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++, &ret));
     if (format & xAdvance) {
-      if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values));
+      if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
       values++;
     }
     /* y_advance values grow downward but font-space grows upward, hence negation */
     if (format & yAdvance) {
-      if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values));
+      if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
       values++;
     }
 
-    if (!has_device ()) return;
+    if (!has_device ()) return ret;
 
     bool use_x_device = font->x_ppem || font->num_coords;
     bool use_y_device = font->y_ppem || font->num_coords;
 
-    if (!use_x_device && !use_y_device) return;
+    if (!use_x_device && !use_y_device) return ret;
 
     const VariationStore &store = c->var_store;
 
     /* pixel -> fractional pixel */
     if (format & xPlaDevice) {
-      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values)).get_x_delta (font, store);
+      if (use_x_device) glyph_pos.x_offset  += (base + get_device (values, &ret)).get_x_delta (font, store);
       values++;
     }
     if (format & yPlaDevice) {
-      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values)).get_y_delta (font, store);
+      if (use_y_device) glyph_pos.y_offset  += (base + get_device (values, &ret)).get_y_delta (font, store);
       values++;
     }
     if (format & xAdvDevice) {
-      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values)).get_x_delta (font, store);
+      if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
       values++;
     }
     if (format & yAdvDevice) {
       /* y_advance values grow downward but font-space grows upward, hence negation */
-      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values)).get_y_delta (font, store);
+      if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
       values++;
     }
+    return ret;
   }
 
   private:
-  inline bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
   {
     unsigned int format = *this;
 
@@ -173,33 +173,40 @@
     return true;
   }
 
-  static inline OffsetTo<Device>& get_device (Value* value)
-  { return *CastP<OffsetTo<Device> > (value); }
-  static inline const OffsetTo<Device>& get_device (const Value* value)
+  static OffsetTo<Device>& get_device (Value* value)
   { return *CastP<OffsetTo<Device> > (value); }
+  static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
+  {
+    if (worked) *worked |= bool (*value);
+    return *CastP<OffsetTo<Device> > (value);
+  }
 
-  static inline const HBINT16& get_short (const Value* value)
-  { return *CastP<HBINT16> (value); }
+  static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
+  {
+    if (worked) *worked |= bool (*value);
+    return *CastP<HBINT16> (value);
+  }
 
   public:
 
-  inline bool has_device (void) const {
+  bool has_device () const
+  {
     unsigned int format = *this;
     return (format & devices) != 0;
   }
 
-  inline bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+  bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
   }
 
-  inline bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+  bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
   {
     TRACE_SANITIZE (this);
     unsigned int len = get_len ();
 
-    if (!c->check_array (values, get_size (), count)) return_trace (false);
+    if (!c->check_range (values, count, get_size ())) return_trace (false);
 
     if (!has_device ()) return_trace (true);
 
@@ -213,7 +220,7 @@
   }
 
   /* Just sanitize referenced Device tables.  Doesn't check the values themselves. */
-  inline bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+  bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
   {
     TRACE_SANITIZE (this);
 
@@ -232,15 +239,15 @@
 
 struct AnchorFormat1
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-                          float *x, float *y) const
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+                   float *x, float *y) const
   {
     hb_font_t *font = c->font;
     *x = font->em_fscale_x (xCoordinate);
     *y = font->em_fscale_y (yCoordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -256,22 +263,22 @@
 
 struct AnchorFormat2
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
-                          float *x, float *y) const
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+                   float *x, float *y) const
   {
     hb_font_t *font = c->font;
     unsigned int x_ppem = font->x_ppem;
     unsigned int y_ppem = font->y_ppem;
     hb_position_t cx = 0, cy = 0;
-    hb_bool_t ret;
+    bool ret;
 
     ret = (x_ppem || y_ppem) &&
-           font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+          font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
     *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
     *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -288,8 +295,8 @@
 
 struct AnchorFormat3
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
-                          float *x, float *y) const
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+                   float *x, float *y) const
   {
     hb_font_t *font = c->font;
     *x = font->em_fscale_x (xCoordinate);
@@ -301,7 +308,7 @@
       *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
@@ -325,8 +332,8 @@
 
 struct Anchor
 {
-  inline void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
-                          float *x, float *y) const
+  void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+                   float *x, float *y) const
   {
     *x = *y = 0;
     switch (u.format) {
@@ -337,7 +344,7 @@
     }
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.format.sanitize (c)) return_trace (false);
@@ -363,20 +370,22 @@
 
 struct AnchorMatrix
 {
-  inline const Anchor& get_anchor (unsigned int row, unsigned int col, unsigned int cols, bool *found) const {
+  const Anchor& get_anchor (unsigned int row, unsigned int col,
+                            unsigned int cols, bool *found) const
+  {
     *found = false;
     if (unlikely (row >= rows || col >= cols)) return Null(Anchor);
     *found = !matrixZ[row * cols + col].is_null ();
     return this+matrixZ[row * cols + col];
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+  bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
   {
     TRACE_SANITIZE (this);
     if (!c->check_struct (this)) return_trace (false);
-    if (unlikely (_hb_unsigned_int_mul_overflows (rows, cols))) return_trace (false);
+    if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
     unsigned int count = rows * cols;
-    if (!c->check_array (matrixZ, matrixZ[0].static_size, count)) return_trace (false);
+    if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
     for (unsigned int i = 0; i < count; i++)
       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
     return_trace (true);
@@ -384,8 +393,8 @@
 
   HBUINT16      rows;                   /* Number of rows */
   protected:
-  OffsetTo<Anchor>
-                matrixZ[VAR];           /* Matrix of offsets to Anchor tables--
+  UnsizedArrayOf<OffsetTo<Anchor> >
+                matrixZ;                /* Matrix of offsets to Anchor tables--
                                          * from beginning of AnchorMatrix table */
   public:
   DEFINE_SIZE_ARRAY (2, matrixZ);
@@ -396,7 +405,7 @@
 {
   friend struct MarkArray;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
@@ -413,10 +422,10 @@
 
 struct MarkArray : ArrayOf<MarkRecord>  /* Array of MarkRecords--in Coverage order */
 {
-  inline bool apply (hb_ot_apply_context_t *c,
-                     unsigned int mark_index, unsigned int glyph_index,
-                     const AnchorMatrix &anchors, unsigned int class_count,
-                     unsigned int glyph_pos) const
+  bool apply (hb_ot_apply_context_t *c,
+              unsigned int mark_index, unsigned int glyph_index,
+              const AnchorMatrix &anchors, unsigned int class_count,
+              unsigned int glyph_pos) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -447,7 +456,7 @@
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ArrayOf<MarkRecord>::sanitize (c, this));
@@ -459,18 +468,15 @@
 
 struct SinglePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -483,7 +489,14 @@
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -507,18 +520,15 @@
 
 struct SinglePosFormat2
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -535,7 +545,14 @@
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -560,7 +577,7 @@
 struct SinglePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -598,19 +615,36 @@
 {
   friend struct PairPosFormat1;
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c,
-                              const ValueFormat *valueFormats) const
+  bool intersects (const hb_set_t *glyphs,
+                          const ValueFormat *valueFormats) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     unsigned int len1 = valueFormats[0].get_len ();
     unsigned int len2 = valueFormats[1].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+    const PairValueRecord *record = &firstPairValueRecord;
+    unsigned int count = len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (glyphs->has (record->secondGlyph))
+        return true;
+      record = &StructAtOffset<const PairValueRecord> (record, record_size);
+    }
+    return false;
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                              const ValueFormat *valueFormats) const
+  {
+    unsigned int len1 = valueFormats[0].get_len ();
+    unsigned int len2 = valueFormats[1].get_len ();
+    unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+    const PairValueRecord *record = &firstPairValueRecord;
     c->input->add_array (&record->secondGlyph, len, record_size);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c,
+  bool apply (hb_ot_apply_context_t *c,
                      const ValueFormat *valueFormats,
                      unsigned int pos) const
   {
@@ -620,7 +654,6 @@
     unsigned int len2 = valueFormats[1].get_len ();
     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
 
-    const PairValueRecord *record_array = CastP<PairValueRecord> (arrayZ);
     unsigned int count = len;
 
     /* Hand-coded bsearch. */
@@ -630,8 +663,8 @@
     int min = 0, max = (int) count - 1;
     while (min <= max)
     {
-      int mid = (min + max) / 2;
-      const PairValueRecord *record = &StructAtOffset<PairValueRecord> (record_array, record_size * mid);
+      int mid = ((unsigned int) min + (unsigned int) max) / 2;
+      const PairValueRecord *record = &StructAtOffset<PairValueRecord> (&firstPairValueRecord, record_size * mid);
       hb_codepoint_t mid_x = record->secondGlyph;
       if (x < mid_x)
         max = mid - 1;
@@ -639,9 +672,10 @@
         min = mid + 1;
       else
       {
-        buffer->unsafe_to_break (buffer->idx, pos + 1);
-        valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
-        valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+        /* Note the intentional use of "|" instead of short-circuit "||". */
+        if (valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos()) |
+            valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]))
+          buffer->unsafe_to_break (buffer->idx, pos + 1);
         if (len2)
           pos++;
         buffer->idx = pos;
@@ -652,50 +686,65 @@
     return_trace (false);
   }
 
-  struct sanitize_closure_t {
+  struct sanitize_closure_t
+  {
     const void *base;
     const ValueFormat *valueFormats;
     unsigned int len1; /* valueFormats[0].get_len() */
     unsigned int stride; /* 1 + len1 + len2 */
   };
 
-  inline bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+  bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
-       && c->check_array (arrayZ, HBUINT16::static_size * closure->stride, len))) return_trace (false);
+       && c->check_range (&firstPairValueRecord,
+                          len,
+                          HBUINT16::static_size,
+                          closure->stride))) return_trace (false);
 
     unsigned int count = len;
-    const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
+    const PairValueRecord *record = &firstPairValueRecord;
     return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, closure->base, &record->values[0], count, closure->stride) &&
                   closure->valueFormats[1].sanitize_values_stride_unsafe (c, closure->base, &record->values[closure->len1], count, closure->stride));
   }
 
   protected:
-  HBUINT16      len;                    /* Number of PairValueRecords */
-  HBUINT16      arrayZ[VAR];            /* Array of PairValueRecords--ordered
-                                         * by GlyphID of the second glyph */
+  HBUINT16              len;    /* Number of PairValueRecords */
+  PairValueRecord       firstPairValueRecord;
+                                /* Array of PairValueRecords--ordered
+                                 * by GlyphID of the second glyph */
   public:
-  DEFINE_SIZE_ARRAY (2, arrayZ);
+  DEFINE_SIZE_MIN (2);
 };
 
 struct PairPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_COLLECT_GLYPHS (this);
+    unsigned int count = pairSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+          (this+pairSet[iter.get_coverage ()]).intersects (glyphs, valueFormat))
+        return true;
+    }
+    return false;
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     unsigned int count = pairSet.len;
     for (unsigned int i = 0; i < count; i++)
       (this+pairSet[i]).collect_glyphs (c, valueFormat);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -709,7 +758,14 @@
     return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
 
@@ -717,7 +773,8 @@
 
     unsigned int len1 = valueFormat[0].get_len ();
     unsigned int len2 = valueFormat[1].get_len ();
-    PairSet::sanitize_closure_t closure = {
+    PairSet::sanitize_closure_t closure =
+    {
       this,
       valueFormat,
       len1,
@@ -747,19 +804,21 @@
 
 struct PairPosFormat2
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_COLLECT_GLYPHS (this);
+    return (this+coverage).intersects (glyphs) &&
+           (this+classDef2).intersects (glyphs);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     if (unlikely (!(this+classDef2).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -778,10 +837,11 @@
     unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
     if (unlikely (klass1 >= class1Count || klass2 >= class2Count)) return_trace (false);
 
-    buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-    valueFormat1.apply_value (c, this, v, buffer->cur_pos());
-    valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+    /* Note the intentional use of "|" instead of short-circuit "||". */
+    if (valueFormat1.apply_value (c, this, v, buffer->cur_pos()) |
+        valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]))
+      buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
 
     buffer->idx = skippy_iter.idx;
     if (len2)
@@ -790,7 +850,14 @@
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!(c->check_struct (this)
@@ -803,7 +870,9 @@
     unsigned int stride = len1 + len2;
     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
     unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
-    return_trace (c->check_array (values, record_size, count) &&
+    return_trace (c->check_range ((const void *) values,
+                                  count,
+                                  record_size) &&
                   valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
                   valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
   }
@@ -841,7 +910,7 @@
 struct PairPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -865,7 +934,7 @@
 {
   friend struct CursivePosFormat1;
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
@@ -889,39 +958,36 @@
 
 struct CursivePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-  }
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { if (unlikely (!(this+coverage).add_coverage (c->input))) return; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
 
     const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage  (buffer->cur().codepoint)];
-    if (!this_record.exitAnchor) return_trace (false);
+    if (!this_record.entryAnchor) return_trace (false);
 
     hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
     skippy_iter.reset (buffer->idx, 1);
-    if (!skippy_iter.next ()) return_trace (false);
+    if (!skippy_iter.prev ()) return_trace (false);
 
-    const EntryExitRecord &next_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
-    if (!next_record.entryAnchor) return_trace (false);
+    const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage  (buffer->info[skippy_iter.idx].codepoint)];
+    if (!prev_record.exitAnchor) return_trace (false);
 
-    unsigned int i = buffer->idx;
-    unsigned int j = skippy_iter.idx;
+    unsigned int i = skippy_iter.idx;
+    unsigned int j = buffer->idx;
 
     buffer->unsafe_to_break (i, j);
     float entry_x, entry_y, exit_x, exit_y;
-    (this+this_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
-    (this+next_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
+    (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
+    (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
 
     hb_glyph_position_t *pos = buffer->pos;
 
@@ -968,7 +1034,7 @@
      * parent.
      *
      * Optimize things for the case of RightToLeft, as that's most common in
-     * Arabinc. */
+     * Arabic. */
     unsigned int child  = i;
     unsigned int parent = j;
     hb_position_t x_offset = entry_x - exit_x;
@@ -997,11 +1063,18 @@
     else
       pos[child].x_offset = x_offset;
 
-    buffer->idx = j;
+    buffer->idx++;
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
@@ -1022,7 +1095,7 @@
 struct CursivePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1047,19 +1120,19 @@
 
 struct MarkBasePosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+markCoverage).intersects (glyphs) &&
+           (this+baseCoverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
     if (unlikely (!(this+baseCoverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+markCoverage;
-  }
+  const Coverage &get_coverage () const { return this+markCoverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1088,7 +1161,7 @@
            ))
         break;
       skippy_iter.reject ();
-    } while (1);
+    } while (true);
 
     /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
     //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
@@ -1099,7 +1172,14 @@
     return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1131,7 +1211,7 @@
 struct MarkBasePos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1161,19 +1241,19 @@
 
 struct MarkLigPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+markCoverage).intersects (glyphs) &&
+           (this+ligatureCoverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+markCoverage).add_coverage (c->input))) return;
     if (unlikely (!(this+ligatureCoverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+markCoverage;
-  }
+  const Coverage &get_coverage () const { return this+markCoverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1216,7 +1296,14 @@
     return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1249,7 +1336,7 @@
 struct MarkLigPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1274,19 +1361,19 @@
 
 struct MarkMarkPosFormat1
 {
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+mark1Coverage).intersects (glyphs) &&
+           (this+mark2Coverage).intersects (glyphs); }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+mark1Coverage).add_coverage (c->input))) return;
     if (unlikely (!(this+mark2Coverage).add_coverage (c->input))) return;
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+mark1Coverage;
-  }
+  const Coverage &get_coverage () const { return this+mark1Coverage; }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_buffer_t *buffer = c->buffer;
@@ -1330,7 +1417,14 @@
     return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -1364,7 +1458,7 @@
 struct MarkMarkPos
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1388,7 +1482,7 @@
 
 struct ExtensionPos : Extension<ExtensionPos>
 {
-  typedef struct PosLookupSubTable LookupSubTable;
+  typedef struct PosLookupSubTable SubTable;
 };
 
 
@@ -1400,6 +1494,7 @@
 
 struct PosLookupSubTable
 {
+  friend struct Lookup;
   friend struct PosLookup;
 
   enum Type {
@@ -1415,10 +1510,9 @@
   };
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
     switch (lookup_type) {
     case Single:                return_trace (u.single.dispatch (c));
     case Pair:                  return_trace (u.pair.dispatch (c));
@@ -1435,7 +1529,6 @@
 
   protected:
   union {
-  HBUINT16              sub_format;
   SinglePos             single;
   PairPos               pair;
   CursivePos            cursive;
@@ -1447,34 +1540,39 @@
   ExtensionPos          extension;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, sub_format);
+  DEFINE_SIZE_MIN (0);
 };
 
 
 struct PosLookup : Lookup
 {
-  inline const PosLookupSubTable& get_subtable (unsigned int i) const
-  { return Lookup::get_subtable<PosLookupSubTable> (i); }
+  typedef struct PosLookupSubTable SubTable;
 
-  inline bool is_reverse (void) const
+  const SubTable& get_subtable (unsigned int i) const
+  { return Lookup::get_subtable<SubTable> (i); }
+
+  bool is_reverse () const
   {
     return false;
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
   }
 
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_COLLECT_GLYPHS (this);
-    return_trace (dispatch (c));
+    hb_intersects_context_t c (glyphs);
+    return dispatch (&c);
   }
 
+  hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { return dispatch (c); }
+
   template <typename set_t>
-  inline void add_coverage (set_t *glyphs) const
+  void add_coverage (set_t *glyphs) const
   {
     hb_add_coverage_context_t<set_t> c (glyphs);
     dispatch (&c);
@@ -1483,22 +1581,19 @@
   static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
-  static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+  static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<PosLookupSubTable> (c); }
+  typename context_t::return_t dispatch (context_t *c) const
+  { return Lookup::dispatch<SubTable> (c); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
-    return_trace (dispatch (c));
-  }
+  bool subset (hb_subset_context_t *c) const
+  { return Lookup::subset<SubTable> (c); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return Lookup::sanitize<SubTable> (c); }
 };
 
-typedef OffsetListOf<PosLookup> PosLookupList;
-
 /*
  * GPOS -- Glyph Positioning
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
@@ -1506,22 +1601,25 @@
 
 struct GPOS : GSUBGPOS
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_GPOS;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
 
-  inline const PosLookup& get_lookup (unsigned int i) const
+  const PosLookup& get_lookup (unsigned int i) const
   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
 
   static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
   static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
   static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
-    const OffsetTo<PosLookupList> &list = CastR<OffsetTo<PosLookupList> > (lookupList);
-    return_trace (list.sanitize (c, this));
-  }
+  bool subset (hb_subset_context_t *c) const
+  { return GSUBGPOS::subset<PosLookup> (c); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return GSUBGPOS::sanitize<PosLookup> (c); }
+
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                   hb_face_t *face) const;
+
+  typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
 };
 
 
@@ -1551,7 +1649,10 @@
   pos[j].attach_type() = type;
 }
 static void
-propagate_attachment_offsets (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction)
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+                              unsigned int len,
+                              unsigned int i,
+                              hb_direction_t direction)
 {
   /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
    * offset of glyph they are attached to. */
@@ -1559,11 +1660,14 @@
   if (likely (!chain))
     return;
 
+  pos[i].attach_chain() = 0;
+
   unsigned int j = (int) i + chain;
 
-  pos[i].attach_chain() = 0;
+  if (unlikely (j >= len))
+    return;
 
-  propagate_attachment_offsets (pos, j, direction);
+  propagate_attachment_offsets (pos, len, j, direction);
 
   assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
 
@@ -1602,7 +1706,7 @@
 }
 
 void
-GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
+GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
 {
   //_hb_buffer_assert_gsubgpos_vars (buffer);
 }
@@ -1619,24 +1723,25 @@
   /* Handle attachments */
   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
     for (unsigned int i = 0; i < len; i++)
-      propagate_attachment_offsets (pos, i, direction);
+      propagate_attachment_offsets (pos, len, i, direction);
 }
 
 
+struct GPOS_accelerator_t : GPOS::accelerator_t {};
+
+
 /* Out-of-class implementation for methods recursing */
 
 template <typename context_t>
 /*static*/ inline typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
 {
-  const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
-  const PosLookup &l = gpos.get_lookup (lookup_index);
+  const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
   return l.dispatch (c);
 }
 
 /*static*/ inline bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
-  const GPOS &gpos = *(hb_ot_layout_from_face (c->face)->gpos);
-  const PosLookup &l = gpos.get_lookup (lookup_index);
+  const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
   unsigned int saved_lookup_props = c->lookup_props;
   unsigned int saved_lookup_index = c->lookup_index;
   c->set_lookup_index (lookup_index);
@@ -1648,10 +1753,6 @@
 }
 
 
-#undef attach_chain
-#undef attach_type
-
-
 } /* namespace OT */
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsub-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,34 +29,37 @@
 #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
 #define HB_OT_LAYOUT_GSUB_TABLE_HH
 
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-layout-gsubgpos.hh"
 
 
 namespace OT {
 
 
+static inline void SingleSubst_serialize (hb_serialize_context_t *c,
+                                          hb_array_t<const GlyphID> glyphs,
+                                          hb_array_t<const GlyphID> substitutes);
+
 struct SingleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
        * https://github.com/harfbuzz/harfbuzz/issues/363 */
       hb_codepoint_t glyph_id = iter.get_glyph ();
       if (c->glyphs->has (glyph_id))
-        c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
+        c->out->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       /* TODO Switch to range-based API to work around malicious fonts.
        * https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -65,18 +68,15 @@
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
@@ -91,19 +91,37 @@
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs,
-                         int delta)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  int delta)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    deltaGlyphID.set (delta); /* TODO(serilaize) overflow? */
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
+    deltaGlyphID.set (delta); /* TODO(serialize) overflow? */
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> from;
+    hb_vector_t<GlyphID> to;
+    hb_codepoint_t delta = deltaGlyphID;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (!glyphset.has (iter.get_glyph ())) continue;
+      from.push ()->set (glyph_map[iter.get_glyph ()]);
+      to.push ()->set (glyph_map[(iter.get_glyph () + delta) & 0xFFFF]);
+    }
+    c->serializer->propagate_error (from, to);
+    SingleSubst_serialize (c->serializer, from, to);
+    return_trace (from.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
@@ -122,27 +140,26 @@
 
 struct SingleSubstFormat2
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
-        c->glyphs->add (substitute[iter.get_coverage ()]);
+        c->out->add (substitute[iter.get_coverage ()]);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -150,45 +167,57 @@
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     if (unlikely (index >= substitute.len)) return_trace (false);
 
-    glyph_id = substitute[index];
-    c->replace_glyph (glyph_id);
+    c->replace_glyph (substitute[index]);
 
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<GlyphID> &substitutes,
-                         unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
+    if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    const hb_set_t &glyphset = *c->plan->glyphset;
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+    hb_vector_t<GlyphID> from;
+    hb_vector_t<GlyphID> to;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (!glyphset.has (iter.get_glyph ())) continue;
+      from.push ()->set (glyph_map[iter.get_glyph ()]);
+      to.push ()->set (glyph_map[substitute[iter.get_coverage ()]]);
+    }
+    c->serializer->propagate_error (from, to);
+    SingleSubst_serialize (c->serializer, from, to);
+    return_trace (from.length);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
@@ -208,35 +237,35 @@
 
 struct SingleSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<GlyphID> &substitutes,
-                         unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 2;
     int delta = 0;
-    if (num_glyphs) {
+    if (glyphs.length)
+    {
       format = 1;
       /* TODO(serialize) check for wrap-around */
       delta = substitutes[0] - glyphs[0];
-      for (unsigned int i = 1; i < num_glyphs; i++)
-        if (delta != substitutes[i] - glyphs[i]) {
+      for (unsigned int i = 1; i < glyphs.length; i++)
+        if (delta != (int) (substitutes[i] - glyphs[i])) {
           format = 2;
           break;
         }
     }
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta));
-    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs));
+    case 1: return_trace (u.format1.serialize (c, glyphs, delta));
+    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -255,24 +284,25 @@
   } u;
 };
 
+static inline void
+SingleSubst_serialize (hb_serialize_context_t *c,
+                       hb_array_t<const GlyphID> glyphs,
+                       hb_array_t<const GlyphID> substitutes)
+{ c->start_embed<SingleSubst> ()->serialize (c, glyphs, substitutes); }
 
 struct Sequence
 {
-  inline void closure (hb_closure_context_t *c) const
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
     unsigned int count = substitute.len;
     for (unsigned int i = 0; i < count; i++)
-      c->glyphs->add (substitute[i]);
+      c->out->add (substitute[i]);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    c->output->add_array (substitute.arrayZ, substitute.len);
-  }
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { c->output->add_array (substitute.arrayZ, substitute.len); }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int count = substitute.len;
@@ -304,17 +334,14 @@
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         unsigned int num_glyphs)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    return_trace (substitute.serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (substitute.sanitize (c));
@@ -329,12 +356,13 @@
 
 struct MultipleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = sequence.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -343,27 +371,23 @@
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
     unsigned int count = sequence.len;
     for (unsigned int i = 0; i < count; i++)
-        (this+sequence[i]).collect_glyphs (c);
+      (this+sequence[i]).collect_glyphs (c);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
 
@@ -373,25 +397,33 @@
     return_trace ((this+sequence[index]).apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<unsigned int> &substitute_len_list,
-                         unsigned int num_glyphs,
-                         Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const unsigned int> substitute_len_list,
+                  hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!sequence[i].serialize (c, this).serialize (c,
-                                                                substitute_glyphs_list,
-                                                                substitute_len_list[i]))) return_trace (false);
-    substitute_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int substitute_len = substitute_len_list[i];
+      if (unlikely (!sequence[i].serialize (c, this)
+                                .serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
+        return_trace (false);
+      substitute_glyphs_list += substitute_len;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
@@ -411,24 +443,23 @@
 
 struct MultipleSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<unsigned int> &substitute_len_list,
-                         unsigned int num_glyphs,
-                         Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const unsigned int> substitute_len_list,
+                  hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list));
+    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -445,103 +476,138 @@
   } u;
 };
 
+struct AlternateSet
+{
+  void closure (hb_closure_context_t *c) const
+  {
+    unsigned int count = alternates.len;
+    for (unsigned int i = 0; i < count; i++)
+      c->out->add (alternates[i]);
+  }
 
-typedef ArrayOf<GlyphID> AlternateSet;  /* Array of alternate GlyphIDs--in
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int count = alternates.len;
+
+    if (unlikely (!count)) return_trace (false);
+
+    hb_mask_t glyph_mask = c->buffer->cur().mask;
+    hb_mask_t lookup_mask = c->lookup_mask;
+
+    /* Note: This breaks badly if two features enabled this lookup together. */
+    unsigned int shift = hb_ctz (lookup_mask);
+    unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
+
+    /* If alt_index is MAX, randomize feature if it is the rand feature. */
+    if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
+      alt_index = c->random_number () % count + 1;
+
+    if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
+
+    c->replace_glyph (alternates[alt_index - 1]);
+
+    return_trace (true);
+  }
+
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs)
+  {
+    TRACE_SERIALIZE (this);
+    return_trace (alternates.serialize (c, glyphs));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (alternates.sanitize (c));
+  }
+
+  protected:
+  ArrayOf<GlyphID>
+                alternates;             /* Array of alternate GlyphIDs--in
                                          * arbitrary order */
+  public:
+  DEFINE_SIZE_ARRAY (2, alternates);
+};
 
 struct AlternateSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
+  { return (this+coverage).intersects (glyphs); }
+
+  void closure (hb_closure_context_t *c) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      if (c->glyphs->has (iter.get_glyph ())) {
-        const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
-        unsigned int count = alt_set.len;
-        for (unsigned int i = 0; i < count; i++)
-          c->glyphs->add (alt_set[i]);
-      }
+      if (c->glyphs->has (iter.get_glyph ()))
+        (this+alternateSet[iter.get_coverage ()]).closure (c);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = alternateSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
-      const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
-      c->output->add_array (alt_set.arrayZ, alt_set.len);
+      (this+alternateSet[iter.get_coverage ()]).collect_glyphs (c);
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
 
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
-    const AlternateSet &alt_set = this+alternateSet[index];
-
-    if (unlikely (!alt_set.len)) return_trace (false);
-
-    hb_mask_t glyph_mask = c->buffer->cur().mask;
-    hb_mask_t lookup_mask = c->lookup_mask;
-
-    /* Note: This breaks badly if two features enabled this lookup together. */
-    unsigned int shift = _hb_ctz (lookup_mask);
-    unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
-
-    if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false);
-
-    glyph_id = alt_set[alt_index - 1];
-
-    c->replace_glyph (glyph_id);
-
-    return_trace (true);
+    return_trace ((this+alternateSet[index]).apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<unsigned int> &alternate_len_list,
-                         unsigned int num_glyphs,
-                         Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const unsigned int> alternate_len_list,
+                  hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
-                                                                    alternate_glyphs_list,
-                                                                    alternate_len_list[i]))) return_trace (false);
-    alternate_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int alternate_len = alternate_len_list[i];
+      if (unlikely (!alternateSet[i].serialize (c, this)
+                                    .serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
+        return_trace (false);
+      alternate_glyphs_list += alternate_len;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
@@ -561,24 +627,23 @@
 
 struct AlternateSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &glyphs,
-                         Supplier<unsigned int> &alternate_len_list,
-                         unsigned int num_glyphs,
-                         Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> glyphs,
+                  hb_array_t<const unsigned int> alternate_len_list,
+                  hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list));
+    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
     default:return_trace (false);
     }
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -598,27 +663,34 @@
 
 struct Ligature
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
-    unsigned int count = component.len;
+    unsigned int count = component.lenP1;
+    for (unsigned int i = 1; i < count; i++)
+      if (!glyphs->has (component[i]))
+        return false;
+    return true;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    unsigned int count = component.lenP1;
     for (unsigned int i = 1; i < count; i++)
       if (!c->glyphs->has (component[i]))
         return;
-    c->glyphs->add (ligGlyph);
+    c->out->add (ligGlyph);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
-    c->input->add_array (component.arrayZ, component.len ? component.len - 1 : 0);
+    c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0);
     c->output->add (ligGlyph);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
-    if (c->len != component.len)
+    if (c->len != component.lenP1)
       return_trace (false);
 
     for (unsigned int i = 1; i < c->len; i++)
@@ -628,10 +700,10 @@
     return_trace (true);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    unsigned int count = component.len;
+    unsigned int count = component.lenP1;
 
     if (unlikely (!count)) return_trace (false);
 
@@ -643,7 +715,6 @@
       return_trace (true);
     }
 
-    bool is_mark_ligature = false;
     unsigned int total_component_count = 0;
 
     unsigned int match_length = 0;
@@ -655,7 +726,6 @@
                               nullptr,
                               &match_length,
                               match_positions,
-                              &is_mark_ligature,
                               &total_component_count)))
       return_trace (false);
 
@@ -664,26 +734,24 @@
                   match_positions,
                   match_length,
                   ligGlyph,
-                  is_mark_ligature,
                   total_component_count);
 
     return_trace (true);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         GlyphID ligature,
-                         Supplier<GlyphID> &components, /* Starting from second */
-                         unsigned int num_components /* Including first component */)
+  bool serialize (hb_serialize_context_t *c,
+                  GlyphID ligature,
+                  hb_array_t<const GlyphID> components /* Starting from second */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     ligGlyph = ligature;
-    if (unlikely (!component.serialize (c, components, num_components))) return_trace (false);
+    if (unlikely (!component.serialize (c, components))) return_trace (false);
     return_trace (true);
   }
 
   public:
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
@@ -701,23 +769,30 @@
 
 struct LigatureSet
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
+    unsigned int num_ligs = ligature.len;
+    for (unsigned int i = 0; i < num_ligs; i++)
+      if ((this+ligature[i]).intersects (glyphs))
+        return true;
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
       (this+ligature[i]).closure (c);
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     unsigned int num_ligs = ligature.len;
     for (unsigned int i = 0; i < num_ligs; i++)
       (this+ligature[i]).collect_glyphs (c);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int num_ligs = ligature.len;
@@ -730,7 +805,7 @@
     return_trace (false);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     unsigned int num_ligs = ligature.len;
@@ -743,26 +818,28 @@
     return_trace (false);
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &ligatures,
-                         Supplier<unsigned int> &component_count_list,
-                         unsigned int num_ligatures,
-                         Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> ligatures,
+                  hb_array_t<const unsigned int> component_count_list,
+                  hb_array_t<const GlyphID> &component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false);
-    for (unsigned int i = 0; i < num_ligatures; i++)
-      if (unlikely (!ligature[i].serialize (c, this).serialize (c,
-                                                                ligatures[i],
-                                                                component_list,
-                                                                component_count_list[i]))) return_trace (false);
-    ligatures += num_ligatures;
-    component_count_list += num_ligatures;
+    if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
+    for (unsigned int i = 0; i < ligatures.length; i++)
+    {
+      unsigned int component_count = MAX<int> (component_count_list[i] - 1, 0);
+      if (unlikely (!ligature[i].serialize (c, this)
+                                .serialize (c,
+                                            ligatures[i],
+                                            component_list.sub_array (0, component_count))))
+        return_trace (false);
+      component_list += component_count;
+    }
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (ligature.sanitize (c, this));
@@ -778,12 +855,24 @@
 
 struct LigatureSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
-    Coverage::Iter iter;
     unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+          (this+ligatureSet[iter.get_coverage ()]).intersects (glyphs))
+        return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    unsigned int count = ligatureSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -792,13 +881,11 @@
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-    Coverage::Iter iter;
     unsigned int count = ligatureSet.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
@@ -806,12 +893,9 @@
     }
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
@@ -821,41 +905,49 @@
     return_trace (lig_set.would_apply (c));
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
-    hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
 
-    unsigned int index = (this+coverage).get_coverage (glyph_id);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
     if (likely (index == NOT_COVERED)) return_trace (false);
 
     const LigatureSet &lig_set = this+ligatureSet[index];
     return_trace (lig_set.apply (c));
   }
 
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &first_glyphs,
-                         Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                         unsigned int num_first_glyphs,
-                         Supplier<GlyphID> &ligatures_list,
-                         Supplier<unsigned int> &component_count_list,
-                         Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> first_glyphs,
+                  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                  hb_array_t<const GlyphID> ligatures_list,
+                  hb_array_t<const unsigned int> component_count_list,
+                  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_first_glyphs; i++)
-      if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
-                                                                   ligatures_list,
-                                                                   component_count_list,
-                                                                   ligature_per_first_glyph_count_list[i],
-                                                                   component_list))) return_trace (false);
-    ligature_per_first_glyph_count_list += num_first_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
+    for (unsigned int i = 0; i < first_glyphs.length; i++)
+    {
+      unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
+      if (unlikely (!ligatureSet[i].serialize (c, this)
+                                   .serialize (c,
+                                               ligatures_list.sub_array (0, ligature_count),
+                                               component_count_list.sub_array (0, ligature_count),
+                                               component_list))) return_trace (false);
+      ligatures_list += ligature_count;
+      component_count_list += ligature_count;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, first_glyphs));
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
@@ -875,13 +967,12 @@
 
 struct LigatureSubst
 {
-  inline bool serialize (hb_serialize_context_t *c,
-                         Supplier<GlyphID> &first_glyphs,
-                         Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                         unsigned int num_first_glyphs,
-                         Supplier<GlyphID> &ligatures_list,
-                         Supplier<unsigned int> &component_count_list,
-                         Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize (hb_serialize_context_t *c,
+                  hb_array_t<const GlyphID> first_glyphs,
+                  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                  hb_array_t<const GlyphID> ligatures_list,
+                  hb_array_t<const unsigned int> component_count_list,
+                  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
@@ -891,7 +982,6 @@
     case 1: return_trace (u.format1.serialize (c,
                                                first_glyphs,
                                                ligature_per_first_glyph_count_list,
-                                               num_first_glyphs,
                                                ligatures_list,
                                                component_count_list,
                                                component_list));
@@ -900,7 +990,7 @@
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -924,17 +1014,38 @@
 
 struct ExtensionSubst : Extension<ExtensionSubst>
 {
-  typedef struct SubstLookupSubTable LookupSubTable;
+  typedef struct SubstLookupSubTable SubTable;
 
-  inline bool is_reverse (void) const;
+  bool is_reverse () const;
 };
 
 
 struct ReverseChainSingleSubstFormat1
 {
-  inline void closure (hb_closure_context_t *c) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    unsigned int count;
+
+    count = backtrack.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+backtrack[i]).intersects (glyphs))
+        return false;
+
+    count = lookahead.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (!(this+lookahead[i]).intersects (glyphs))
+        return false;
+
+    return true;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
     const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
 
     unsigned int count;
@@ -950,20 +1061,18 @@
         return;
 
     const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-    Coverage::Iter iter;
     count = substitute.len;
-    for (iter.init (this+coverage); iter.more (); iter.next ())
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
     {
       if (unlikely (iter.get_coverage () >= count))
         break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
       if (c->glyphs->has (iter.get_glyph ()))
-        c->glyphs->add (substitute[iter.get_coverage ()]);
+        c->out->add (substitute[iter.get_coverage ()]);
     }
   }
 
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
 
     unsigned int count;
@@ -982,18 +1091,15 @@
     c->output->add_array (substitute.arrayZ, substitute.len);
   }
 
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
+  const Coverage &get_coverage () const { return this+coverage; }
 
-  inline bool would_apply (hb_would_apply_context_t *c) const
+  bool would_apply (hb_would_apply_context_t *c) const
   {
     TRACE_WOULD_APPLY (this);
     return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
@@ -1026,7 +1132,14 @@
     return_trace (false);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
@@ -1045,7 +1158,7 @@
                                          * beginning of table */
   OffsetArrayOf<Coverage>
                 backtrack;              /* Array of coverage tables
-                                         * in backtracking sequence, in  glyph
+                                         * in backtracking sequence, in glyph
                                          * sequence order */
   OffsetArrayOf<Coverage>
                 lookaheadX;             /* Array of coverage tables
@@ -1061,7 +1174,7 @@
 struct ReverseChainSingleSubst
 {
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
+  typename context_t::return_t dispatch (context_t *c) const
   {
     TRACE_DISPATCH (this, u.format);
     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
@@ -1086,6 +1199,7 @@
 
 struct SubstLookupSubTable
 {
+  friend struct Lookup;
   friend struct SubstLookup;
 
   enum Type {
@@ -1100,10 +1214,9 @@
   };
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
   {
     TRACE_DISPATCH (this, lookup_type);
-    if (unlikely (!c->may_dispatch (this, &u.sub_format))) return_trace (c->no_dispatch_return_value ());
     switch (lookup_type) {
     case Single:                return_trace (u.single.dispatch (c));
     case Multiple:              return_trace (u.multiple.dispatch (c));
@@ -1119,7 +1232,6 @@
 
   protected:
   union {
-  HBUINT16                      sub_format;
   SingleSubst                   single;
   MultipleSubst                 multiple;
   AlternateSubst                alternate;
@@ -1130,58 +1242,69 @@
   ReverseChainSingleSubst       reverseChainContextSingle;
   } u;
   public:
-  DEFINE_SIZE_UNION (2, sub_format);
+  DEFINE_SIZE_MIN (0);
 };
 
 
 struct SubstLookup : Lookup
 {
-  inline const SubstLookupSubTable& get_subtable (unsigned int i) const
-  { return Lookup::get_subtable<SubstLookupSubTable> (i); }
+  typedef SubstLookupSubTable SubTable;
+
+  const SubTable& get_subtable (unsigned int i) const
+  { return Lookup::get_subtable<SubTable> (i); }
 
-  inline static bool lookup_type_is_reverse (unsigned int lookup_type)
-  { return lookup_type == SubstLookupSubTable::ReverseChainSingle; }
+  static bool lookup_type_is_reverse (unsigned int lookup_type)
+  { return lookup_type == SubTable::ReverseChainSingle; }
 
-  inline bool is_reverse (void) const
+  bool is_reverse () const
   {
     unsigned int type = get_type ();
-    if (unlikely (type == SubstLookupSubTable::Extension))
+    if (unlikely (type == SubTable::Extension))
       return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
     return lookup_type_is_reverse (type);
   }
 
-  inline bool apply (hb_ot_apply_context_t *c) const
+  bool apply (hb_ot_apply_context_t *c) const
   {
     TRACE_APPLY (this);
     return_trace (dispatch (c));
   }
 
-  inline hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
+  bool intersects (const hb_set_t *glyphs) const
   {
-    TRACE_CLOSURE (this);
+    hb_intersects_context_t c (glyphs);
+    return dispatch (&c);
+  }
+
+  hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
+  {
     if (!c->should_visit_lookup (this_index))
-      return_trace (HB_VOID);
+      return hb_closure_context_t::default_return_value ();
 
     c->set_recurse_func (dispatch_closure_recurse_func);
-    return_trace (dispatch (c));
+
+    hb_closure_context_t::return_t ret = dispatch (c);
+
+    c->flush ();
+
+    return ret;
   }
 
-  inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+  hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
   {
-    TRACE_COLLECT_GLYPHS (this);
     c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
-    return_trace (dispatch (c));
+    return dispatch (c);
   }
 
   template <typename set_t>
-  inline void add_coverage (set_t *glyphs) const
+  void add_coverage (set_t *glyphs) const
   {
     hb_add_coverage_context_t<set_t> c (glyphs);
     dispatch (&c);
   }
 
-  inline bool would_apply (hb_would_apply_context_t *c,
-                           const hb_ot_layout_lookup_accelerator_t *accel) const
+  bool would_apply (hb_would_apply_context_t *c,
+                    const hb_ot_layout_lookup_accelerator_t *accel) const
   {
     TRACE_WOULD_APPLY (this);
     if (unlikely (!c->len))  return_trace (false);
@@ -1191,111 +1314,95 @@
 
   static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
 
-  inline SubstLookupSubTable& serialize_subtable (hb_serialize_context_t *c,
-                                                  unsigned int i)
-  { return get_subtables<SubstLookupSubTable> ()[i].serialize (c, this); }
+  SubTable& serialize_subtable (hb_serialize_context_t *c,
+                                       unsigned int i)
+  { return get_subtables<SubTable> ()[i].serialize (c, this); }
 
-  inline bool serialize_single (hb_serialize_context_t *c,
-                                uint32_t lookup_props,
-                                Supplier<GlyphID> &glyphs,
-                                Supplier<GlyphID> &substitutes,
-                                unsigned int num_glyphs)
+  bool serialize_single (hb_serialize_context_t *c,
+                         uint32_t lookup_props,
+                         hb_array_t<const GlyphID> glyphs,
+                         hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Single, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs));
+    if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
+    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes));
   }
 
-  inline bool serialize_multiple (hb_serialize_context_t *c,
-                                  uint32_t lookup_props,
-                                  Supplier<GlyphID> &glyphs,
-                                  Supplier<unsigned int> &substitute_len_list,
-                                  unsigned int num_glyphs,
-                                  Supplier<GlyphID> &substitute_glyphs_list)
+  bool serialize_multiple (hb_serialize_context_t *c,
+                           uint32_t lookup_props,
+                           hb_array_t<const GlyphID> glyphs,
+                           hb_array_t<const unsigned int> substitute_len_list,
+                           hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Multiple, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.multiple.serialize (c,
                                                                   glyphs,
                                                                   substitute_len_list,
-                                                                  num_glyphs,
                                                                   substitute_glyphs_list));
   }
 
-  inline bool serialize_alternate (hb_serialize_context_t *c,
-                                   uint32_t lookup_props,
-                                   Supplier<GlyphID> &glyphs,
-                                   Supplier<unsigned int> &alternate_len_list,
-                                   unsigned int num_glyphs,
-                                   Supplier<GlyphID> &alternate_glyphs_list)
+  bool serialize_alternate (hb_serialize_context_t *c,
+                            uint32_t lookup_props,
+                            hb_array_t<const GlyphID> glyphs,
+                            hb_array_t<const unsigned int> alternate_len_list,
+                            hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Alternate, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.alternate.serialize (c,
                                                                    glyphs,
                                                                    alternate_len_list,
-                                                                   num_glyphs,
                                                                    alternate_glyphs_list));
   }
 
-  inline bool serialize_ligature (hb_serialize_context_t *c,
-                                  uint32_t lookup_props,
-                                  Supplier<GlyphID> &first_glyphs,
-                                  Supplier<unsigned int> &ligature_per_first_glyph_count_list,
-                                  unsigned int num_first_glyphs,
-                                  Supplier<GlyphID> &ligatures_list,
-                                  Supplier<unsigned int> &component_count_list,
-                                  Supplier<GlyphID> &component_list /* Starting from second for each ligature */)
+  bool serialize_ligature (hb_serialize_context_t *c,
+                           uint32_t lookup_props,
+                           hb_array_t<const GlyphID> first_glyphs,
+                           hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+                           hb_array_t<const GlyphID> ligatures_list,
+                           hb_array_t<const unsigned int> component_count_list,
+                           hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!Lookup::serialize (c, SubstLookupSubTable::Ligature, lookup_props, 1))) return_trace (false);
+    if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.ligature.serialize (c,
                                                                   first_glyphs,
                                                                   ligature_per_first_glyph_count_list,
-                                                                  num_first_glyphs,
                                                                   ligatures_list,
                                                                   component_count_list,
                                                                   component_list));
   }
 
   template <typename context_t>
-  static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+  static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
 
-  static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
+  static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
   {
     if (!c->should_visit_lookup (lookup_index))
       return HB_VOID;
-    return dispatch_recurse_func (c, lookup_index);
+
+    hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
+
+    /* While in theory we should flush here, it will cause timeouts because a recursive
+     * lookup can keep growing the glyph set.  Skip, and outer loop will retry up to
+     * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
+    //c->flush ();
+
+    return ret;
   }
 
   template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  { return Lookup::dispatch<SubstLookupSubTable> (c); }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!Lookup::sanitize (c))) return_trace (false);
-    if (unlikely (!dispatch (c))) return_trace (false);
+  typename context_t::return_t dispatch (context_t *c) const
+  { return Lookup::dispatch<SubTable> (c); }
 
-    if (unlikely (get_type () == SubstLookupSubTable::Extension))
-    {
-      /* The spec says all subtables of an Extension lookup should
-       * have the same type, which shall not be the Extension type
-       * itself (but we already checked for that).
-       * This is specially important if one has a reverse type! */
-      unsigned int type = get_subtable (0).u.extension.get_type ();
-      unsigned int count = get_subtable_count ();
-      for (unsigned int i = 1; i < count; i++)
-        if (get_subtable (i).u.extension.get_type () != type)
-          return_trace (false);
-    }
-    return_trace (true);
-  }
+  bool subset (hb_subset_context_t *c) const
+  { return Lookup::subset<SubTable> (c); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return Lookup::sanitize<SubTable> (c); }
 };
 
-typedef OffsetListOf<SubstLookup> SubstLookupList;
-
 /*
  * GSUB -- Glyph Substitution
  * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
@@ -1303,61 +1410,47 @@
 
 struct GSUB : GSUBGPOS
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_GSUB;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
 
-  inline const SubstLookup& get_lookup (unsigned int i) const
+  const SubstLookup& get_lookup (unsigned int i) const
   { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
 
-  static inline void substitute_start (hb_font_t *font, hb_buffer_t *buffer);
+  bool subset (hb_subset_context_t *c) const
+  { return GSUBGPOS::subset<SubstLookup> (c); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!GSUBGPOS::sanitize (c))) return_trace (false);
-    const OffsetTo<SubstLookupList> &list = CastR<OffsetTo<SubstLookupList> > (lookupList);
-    return_trace (list.sanitize (c, this));
-  }
+  bool sanitize (hb_sanitize_context_t *c) const
+  { return GSUBGPOS::sanitize<SubstLookup> (c); }
+
+  HB_INTERNAL bool is_blacklisted (hb_blob_t *blob,
+                                   hb_face_t *face) const;
+
+  typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
 };
 
 
-void
-GSUB::substitute_start (hb_font_t *font, hb_buffer_t *buffer)
-{
-  _hb_buffer_assert_gsubgpos_vars (buffer);
-
-  const GDEF &gdef = *hb_ot_layout_from_face (font->face)->gdef;
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-  {
-    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
-    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
-    buffer->info[i].syllable() = 0;
-  }
-}
+struct GSUB_accelerator_t : GSUB::accelerator_t {};
 
 
 /* Out-of-class implementation for methods recursing */
 
-/*static*/ inline bool ExtensionSubst::is_reverse (void) const
+/*static*/ inline bool ExtensionSubst::is_reverse () const
 {
   unsigned int type = get_type ();
-  if (unlikely (type == SubstLookupSubTable::Extension))
-    return CastR<ExtensionSubst> (get_subtable<LookupSubTable>()).is_reverse ();
+  if (unlikely (type == SubTable::Extension))
+    return CastR<ExtensionSubst> (get_subtable<SubTable>()).is_reverse ();
   return SubstLookup::lookup_type_is_reverse (type);
 }
 
 template <typename context_t>
 /*static*/ inline typename context_t::return_t SubstLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
 {
-  const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
-  const SubstLookup &l = gsub.get_lookup (lookup_index);
+  const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
   return l.dispatch (c);
 }
 
 /*static*/ inline bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
 {
-  const GSUB &gsub = *(hb_ot_layout_from_face (c->face)->gsub);
-  const SubstLookup &l = gsub.get_lookup (lookup_index);
+  const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
   unsigned int saved_lookup_props = c->lookup_props;
   unsigned int saved_lookup_index = c->lookup_index;
   c->set_lookup_index (lookup_index);
@@ -1368,7 +1461,6 @@
   return ret;
 }
 
-
 } /* namespace OT */
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2394 +0,0 @@
-/*
- * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
-#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-buffer-private.hh"
-#include "hb-map-private.hh"
-#include "hb-ot-layout-gdef-table.hh"
-#include "hb-set-private.hh"
-
-
-namespace OT {
-
-
-struct hb_closure_context_t :
-       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
-{
-  inline const char *get_name (void) { return "CLOSURE"; }
-  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    nesting_level_left--;
-    recurse_func (this, lookup_index);
-    nesting_level_left++;
-    return HB_VOID;
-  }
-
-  bool should_visit_lookup (unsigned int lookup_index)
-  {
-    if (is_lookup_done (lookup_index))
-      return false;
-    done_lookups->set (lookup_index, glyphs->get_population ());
-    return true;
-  }
-
-  bool is_lookup_done (unsigned int lookup_index)
-  {
-    // Have we visited this lookup with the current set of glyphs?
-    return done_lookups->get (lookup_index) == glyphs->get_population ();
-  }
-
-  hb_face_t *face;
-  hb_set_t *glyphs;
-  recurse_func_t recurse_func;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  hb_closure_context_t (hb_face_t *face_,
-                        hb_set_t *glyphs_,
-                        hb_map_t *done_lookups_,
-                        unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-                          face (face_),
-                          glyphs (glyphs_),
-                          recurse_func (nullptr),
-                          nesting_level_left (nesting_level_left_),
-                          debug_depth (0),
-                          done_lookups (done_lookups_) {}
-
-  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-
-  private:
-  hb_map_t *done_lookups;
-};
-
-
-struct hb_would_apply_context_t :
-       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
-{
-  inline const char *get_name (void) { return "WOULD_APPLY"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-
-  hb_face_t *face;
-  const hb_codepoint_t *glyphs;
-  unsigned int len;
-  bool zero_context;
-  unsigned int debug_depth;
-
-  hb_would_apply_context_t (hb_face_t *face_,
-                            const hb_codepoint_t *glyphs_,
-                            unsigned int len_,
-                            bool zero_context_) :
-                              face (face_),
-                              glyphs (glyphs_),
-                              len (len_),
-                              zero_context (zero_context_),
-                              debug_depth (0) {}
-};
-
-
-struct hb_collect_glyphs_context_t :
-       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
-{
-  inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
-  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-  return_t recurse (unsigned int lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func))
-      return default_return_value ();
-
-    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
-     * past the previous check.  For GSUB, we only want to collect the output
-     * glyphs in the recursion.  If output is not requested, we can go home now.
-     *
-     * Note further, that the above is not exactly correct.  A recursed lookup
-     * is allowed to match input that is not matched in the context, but that's
-     * not how most fonts are built.  It's possible to relax that and recurse
-     * with all sets here if it proves to be an issue.
-     */
-
-    if (output == hb_set_get_empty ())
-      return HB_VOID;
-
-    /* Return if new lookup was recursed to before. */
-    if (recursed_lookups->has (lookup_index))
-      return HB_VOID;
-
-    hb_set_t *old_before = before;
-    hb_set_t *old_input  = input;
-    hb_set_t *old_after  = after;
-    before = input = after = hb_set_get_empty ();
-
-    nesting_level_left--;
-    recurse_func (this, lookup_index);
-    nesting_level_left++;
-
-    before = old_before;
-    input  = old_input;
-    after  = old_after;
-
-    recursed_lookups->add (lookup_index);
-
-    return HB_VOID;
-  }
-
-  hb_face_t *face;
-  hb_set_t *before;
-  hb_set_t *input;
-  hb_set_t *after;
-  hb_set_t *output;
-  recurse_func_t recurse_func;
-  hb_set_t *recursed_lookups;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  hb_collect_glyphs_context_t (hb_face_t *face_,
-                               hb_set_t  *glyphs_before, /* OUT. May be nullptr */
-                               hb_set_t  *glyphs_input,  /* OUT. May be nullptr */
-                               hb_set_t  *glyphs_after,  /* OUT. May be nullptr */
-                               hb_set_t  *glyphs_output, /* OUT. May be nullptr */
-                               unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-                              face (face_),
-                              before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
-                              input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
-                              after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
-                              output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
-                              recurse_func (nullptr),
-                              recursed_lookups (nullptr),
-                              nesting_level_left (nesting_level_left_),
-                              debug_depth (0)
-  {
-    recursed_lookups = hb_set_create ();
-  }
-  ~hb_collect_glyphs_context_t (void)
-  {
-    hb_set_destroy (recursed_lookups);
-  }
-
-  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-};
-
-
-
-/* XXX Can we remove this? */
-
-template <typename set_t>
-struct hb_add_coverage_context_t :
-       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
-{
-  inline const char *get_name (void) { return "GET_COVERAGE"; }
-  typedef const Coverage &return_t;
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
-  static return_t default_return_value (void) { return Null(Coverage); }
-  bool stop_sublookup_iteration (return_t r) const
-  {
-    r.add_coverage (set);
-    return false;
-  }
-
-  hb_add_coverage_context_t (set_t *set_) :
-                            set (set_),
-                            debug_depth (0) {}
-
-  set_t *set;
-  unsigned int debug_depth;
-};
-
-
-struct hb_ot_apply_context_t :
-       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
-{
-  struct matcher_t
-  {
-    inline matcher_t (void) :
-             lookup_props (0),
-             ignore_zwnj (false),
-             ignore_zwj (false),
-             mask (-1),
-#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
-             syllable arg1(0),
-#undef arg1
-             match_func (nullptr),
-             match_data (nullptr) {};
-
-    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
-
-    inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
-    inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
-    inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
-    inline void set_mask (hb_mask_t mask_) { mask = mask_; }
-    inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
-    inline void set_match_func (match_func_t match_func_,
-                                const void *match_data_)
-    { match_func = match_func_; match_data = match_data_; }
-
-    enum may_match_t {
-      MATCH_NO,
-      MATCH_YES,
-      MATCH_MAYBE
-    };
-
-    inline may_match_t may_match (const hb_glyph_info_t &info,
-                                  const HBUINT16          *glyph_data) const
-    {
-      if (!(info.mask & mask) ||
-          (syllable && syllable != info.syllable ()))
-        return MATCH_NO;
-
-      if (match_func)
-        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
-
-      return MATCH_MAYBE;
-    }
-
-    enum may_skip_t {
-      SKIP_NO,
-      SKIP_YES,
-      SKIP_MAYBE
-    };
-
-    inline may_skip_t
-    may_skip (const hb_ot_apply_context_t *c,
-              const hb_glyph_info_t    &info) const
-    {
-      if (!c->check_glyph_property (&info, lookup_props))
-        return SKIP_YES;
-
-      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
-                    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
-                    (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
-        return SKIP_MAYBE;
-
-      return SKIP_NO;
-    }
-
-    protected:
-    unsigned int lookup_props;
-    bool ignore_zwnj;
-    bool ignore_zwj;
-    hb_mask_t mask;
-    uint8_t syllable;
-    match_func_t match_func;
-    const void *match_data;
-  };
-
-  struct skipping_iterator_t
-  {
-    inline void init (hb_ot_apply_context_t *c_, bool context_match = false)
-    {
-      c = c_;
-      match_glyph_data = nullptr;
-      matcher.set_match_func (nullptr, nullptr);
-      matcher.set_lookup_props (c->lookup_props);
-      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
-      matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
-      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
-      matcher.set_ignore_zwj  (c->table_index == 1 || (context_match || c->auto_zwj));
-      matcher.set_mask (context_match ? -1 : c->lookup_mask);
-    }
-    inline void set_lookup_props (unsigned int lookup_props)
-    {
-      matcher.set_lookup_props (lookup_props);
-    }
-    inline void set_match_func (matcher_t::match_func_t match_func_,
-                                const void *match_data_,
-                                const HBUINT16 glyph_data[])
-    {
-      matcher.set_match_func (match_func_, match_data_);
-      match_glyph_data = glyph_data;
-    }
-
-    inline void reset (unsigned int start_index_,
-                       unsigned int num_items_)
-    {
-      idx = start_index_;
-      num_items = num_items_;
-      end = c->buffer->len;
-      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
-    }
-
-    inline void reject (void) { num_items++; match_glyph_data--; }
-
-    inline matcher_t::may_skip_t
-    may_skip (const hb_glyph_info_t    &info) const
-    {
-      return matcher.may_skip (c, info);
-    }
-
-    inline bool next (void)
-    {
-      assert (num_items > 0);
-      while (idx + num_items < end)
-      {
-        idx++;
-        const hb_glyph_info_t &info = c->buffer->info[idx];
-
-        matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-        if (unlikely (skip == matcher_t::SKIP_YES))
-          continue;
-
-        matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-        if (match == matcher_t::MATCH_YES ||
-            (match == matcher_t::MATCH_MAYBE &&
-             skip == matcher_t::SKIP_NO))
-        {
-          num_items--;
-          match_glyph_data++;
-          return true;
-        }
-
-        if (skip == matcher_t::SKIP_NO)
-          return false;
-      }
-      return false;
-    }
-    inline bool prev (void)
-    {
-      assert (num_items > 0);
-      while (idx >= num_items)
-      {
-        idx--;
-        const hb_glyph_info_t &info = c->buffer->out_info[idx];
-
-        matcher_t::may_skip_t skip = matcher.may_skip (c, info);
-        if (unlikely (skip == matcher_t::SKIP_YES))
-          continue;
-
-        matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
-        if (match == matcher_t::MATCH_YES ||
-            (match == matcher_t::MATCH_MAYBE &&
-             skip == matcher_t::SKIP_NO))
-        {
-          num_items--;
-          match_glyph_data++;
-          return true;
-        }
-
-        if (skip == matcher_t::SKIP_NO)
-          return false;
-      }
-      return false;
-    }
-
-    unsigned int idx;
-    protected:
-    hb_ot_apply_context_t *c;
-    matcher_t matcher;
-    const HBUINT16 *match_glyph_data;
-
-    unsigned int num_items;
-    unsigned int end;
-  };
-
-
-  inline const char *get_name (void) { return "APPLY"; }
-  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
-  template <typename T>
-  inline return_t dispatch (const T &obj) { return obj.apply (this); }
-  static return_t default_return_value (void) { return false; }
-  bool stop_sublookup_iteration (return_t r) const { return r; }
-  return_t recurse (unsigned int sub_lookup_index)
-  {
-    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
-      return default_return_value ();
-
-    nesting_level_left--;
-    bool ret = recurse_func (this, sub_lookup_index);
-    nesting_level_left++;
-    return ret;
-  }
-
-  skipping_iterator_t iter_input, iter_context;
-
-  hb_font_t *font;
-  hb_face_t *face;
-  hb_buffer_t *buffer;
-  recurse_func_t recurse_func;
-  const GDEF &gdef;
-  const VariationStore &var_store;
-
-  hb_direction_t direction;
-  hb_mask_t lookup_mask;
-  unsigned int table_index; /* GSUB/GPOS */
-  unsigned int lookup_index;
-  unsigned int lookup_props;
-  unsigned int nesting_level_left;
-  unsigned int debug_depth;
-
-  bool auto_zwnj;
-  bool auto_zwj;
-  bool has_glyph_classes;
-
-
-  hb_ot_apply_context_t (unsigned int table_index_,
-                      hb_font_t *font_,
-                      hb_buffer_t *buffer_) :
-                        iter_input (), iter_context (),
-                        font (font_), face (font->face), buffer (buffer_),
-                        recurse_func (nullptr),
-                        gdef (*hb_ot_layout_from_face (face)->gdef),
-                        var_store (gdef.get_var_store ()),
-                        direction (buffer_->props.direction),
-                        lookup_mask (1),
-                        table_index (table_index_),
-                        lookup_index ((unsigned int) -1),
-                        lookup_props (0),
-                        nesting_level_left (HB_MAX_NESTING_LEVEL),
-                        debug_depth (0),
-                        auto_zwnj (true),
-                        auto_zwj (true),
-                        has_glyph_classes (gdef.has_glyph_classes ()) {}
-
-  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
-  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
-  inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; }
-  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
-  inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
-  inline void set_lookup_props (unsigned int lookup_props_)
-  {
-    lookup_props = lookup_props_;
-    iter_input.init (this, false);
-    iter_context.init (this, true);
-  }
-
-  inline bool
-  match_properties_mark (hb_codepoint_t  glyph,
-                         unsigned int    glyph_props,
-                         unsigned int    match_props) const
-  {
-    /* If using mark filtering sets, the high short of
-     * match_props has the set index.
-     */
-    if (match_props & LookupFlag::UseMarkFilteringSet)
-      return gdef.mark_set_covers (match_props >> 16, glyph);
-
-    /* The second byte of match_props has the meaning
-     * "ignore marks of attachment type different than
-     * the attachment type specified."
-     */
-    if (match_props & LookupFlag::MarkAttachmentType)
-      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
-
-    return true;
-  }
-
-  inline bool
-  check_glyph_property (const hb_glyph_info_t *info,
-                        unsigned int  match_props) const
-  {
-    hb_codepoint_t glyph = info->codepoint;
-    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
-
-    /* Not covered, if, for example, glyph class is ligature and
-     * match_props includes LookupFlags::IgnoreLigatures
-     */
-    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
-      return false;
-
-    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
-      return match_properties_mark (glyph, glyph_props, match_props);
-
-    return true;
-  }
-
-  inline void _set_glyph_props (hb_codepoint_t glyph_index,
-                          unsigned int class_guess = 0,
-                          bool ligature = false,
-                          bool component = false) const
-  {
-    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
-                          HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
-    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
-    if (ligature)
-    {
-      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
-      /* In the only place that the MULTIPLIED bit is used, Uniscribe
-       * seems to only care about the "last" transformation between
-       * Ligature and Multiple substitions.  Ie. if you ligate, expand,
-       * and ligate again, it forgives the multiplication and acts as
-       * if only ligation happened.  As such, clear MULTIPLIED bit.
-       */
-      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
-    }
-    if (component)
-      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
-    if (likely (has_glyph_classes))
-      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
-    else if (class_guess)
-      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
-  }
-
-  inline void replace_glyph (hb_codepoint_t glyph_index) const
-  {
-    _set_glyph_props (glyph_index);
-    buffer->replace_glyph (glyph_index);
-  }
-  inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const
-  {
-    _set_glyph_props (glyph_index);
-    buffer->cur().codepoint = glyph_index;
-  }
-  inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
-                                           unsigned int class_guess) const
-  {
-    _set_glyph_props (glyph_index, class_guess, true);
-    buffer->replace_glyph (glyph_index);
-  }
-  inline void output_glyph_for_component (hb_codepoint_t glyph_index,
-                                          unsigned int class_guess) const
-  {
-    _set_glyph_props (glyph_index, class_guess, false, true);
-    buffer->output_glyph (glyph_index);
-  }
-};
-
-
-
-typedef bool (*intersects_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
-
-struct ContextClosureFuncs
-{
-  intersects_func_t intersects;
-};
-struct ContextCollectGlyphsFuncs
-{
-  collect_glyphs_func_t collect;
-};
-struct ContextApplyFuncs
-{
-  match_func_t match;
-};
-
-
-static inline bool intersects_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  return glyphs->has (value);
-}
-static inline bool intersects_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.intersects_class (glyphs, value);
-}
-static inline bool intersects_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  return (data+coverage).intersects (glyphs);
-}
-
-static inline bool intersects_array (hb_closure_context_t *c,
-                                     unsigned int count,
-                                     const HBUINT16 values[],
-                                     intersects_func_t intersects_func,
-                                     const void *intersects_data)
-{
-  for (unsigned int i = 0; i < count; i++)
-    if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
-      return false;
-  return true;
-}
-
-
-static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  glyphs->add (value);
-}
-static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  class_def.add_class (glyphs, value);
-}
-static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  (data+coverage).add_coverage (glyphs);
-}
-static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
-                                  hb_set_t *glyphs,
-                                  unsigned int count,
-                                  const HBUINT16 values[],
-                                  collect_glyphs_func_t collect_func,
-                                  const void *collect_data)
-{
-  for (unsigned int i = 0; i < count; i++)
-    collect_func (glyphs, values[i], collect_data);
-}
-
-
-static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
-{
-  return glyph_id == value;
-}
-static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-{
-  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
-  return class_def.get_class (glyph_id) == value;
-}
-static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-{
-  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
-  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
-}
-
-static inline bool would_match_input (hb_would_apply_context_t *c,
-                                      unsigned int count, /* Including the first glyph (not matched) */
-                                      const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                      match_func_t match_func,
-                                      const void *match_data)
-{
-  if (count != c->len)
-    return false;
-
-  for (unsigned int i = 1; i < count; i++)
-    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
-      return false;
-
-  return true;
-}
-static inline bool match_input (hb_ot_apply_context_t *c,
-                                unsigned int count, /* Including the first glyph (not matched) */
-                                const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                match_func_t match_func,
-                                const void *match_data,
-                                unsigned int *end_offset,
-                                unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
-                                bool *p_is_mark_ligature = nullptr,
-                                unsigned int *p_total_component_count = nullptr)
-{
-  TRACE_APPLY (nullptr);
-
-  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
-
-  hb_buffer_t *buffer = c->buffer;
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
-  skippy_iter.reset (buffer->idx, count - 1);
-  skippy_iter.set_match_func (match_func, match_data, input);
-
-  /*
-   * This is perhaps the trickiest part of OpenType...  Remarks:
-   *
-   * - If all components of the ligature were marks, we call this a mark ligature.
-   *
-   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
-   *   it as a ligature glyph.
-   *
-   * - Ligatures cannot be formed across glyphs attached to different components
-   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
-   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
-   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
-   *   There are a couple of exceptions to this:
-   *
-   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
-   *     assuming that the font designer knows what they are doing (otherwise it can
-   *     break Indic stuff when a matra wants to ligate with a conjunct,
-   *
-   *   o If two marks want to ligate and they belong to different components of the
-   *     same ligature glyph, and said ligature glyph is to be ignored according to
-   *     mark-filtering rules, then allow.
-   *     https://github.com/harfbuzz/harfbuzz/issues/545
-   */
-
-  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
-
-  unsigned int total_component_count = 0;
-  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-
-  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-
-  enum {
-    LIGBASE_NOT_CHECKED,
-    LIGBASE_MAY_NOT_SKIP,
-    LIGBASE_MAY_SKIP
-  } ligbase = LIGBASE_NOT_CHECKED;
-
-  match_positions[0] = buffer->idx;
-  for (unsigned int i = 1; i < count; i++)
-  {
-    if (!skippy_iter.next ()) return_trace (false);
-
-    match_positions[i] = skippy_iter.idx;
-
-    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
-    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
-
-    if (first_lig_id && first_lig_comp)
-    {
-      /* If first component was attached to a previous ligature component,
-       * all subsequent components should be attached to the same ligature
-       * component, otherwise we shouldn't ligate them... */
-      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
-      {
-        /* ...unless, we are attached to a base ligature and that base
-         * ligature is ignorable. */
-        if (ligbase == LIGBASE_NOT_CHECKED)
-        {
-          bool found = false;
-          const hb_glyph_info_t *out = buffer->out_info;
-          unsigned int j = buffer->out_len;
-          while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
-          {
-            if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
-            {
-              j--;
-              found = true;
-              break;
-            }
-            j--;
-          }
-
-          if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
-            ligbase = LIGBASE_MAY_SKIP;
-          else
-            ligbase = LIGBASE_MAY_NOT_SKIP;
-        }
-
-        if (ligbase == LIGBASE_MAY_NOT_SKIP)
-          return_trace (false);
-      }
-    }
-    else
-    {
-      /* If first component was NOT attached to a previous ligature component,
-       * all subsequent components should also NOT be attached to any ligature
-       * component, unless they are attached to the first component itself! */
-      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
-        return_trace (false);
-    }
-
-    is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
-    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
-  }
-
-  *end_offset = skippy_iter.idx - buffer->idx + 1;
-
-  if (p_is_mark_ligature)
-    *p_is_mark_ligature = is_mark_ligature;
-
-  if (p_total_component_count)
-    *p_total_component_count = total_component_count;
-
-  return_trace (true);
-}
-static inline bool ligate_input (hb_ot_apply_context_t *c,
-                                 unsigned int count, /* Including the first glyph */
-                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
-                                 unsigned int match_length,
-                                 hb_codepoint_t lig_glyph,
-                                 bool is_mark_ligature,
-                                 unsigned int total_component_count)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_buffer_t *buffer = c->buffer;
-
-  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
-
-  /*
-   * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
-   *   the ligature to keep its old ligature id.  This will allow it to attach to
-   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
-   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
-   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
-   *   later, we don't want them to lose their ligature id/component, otherwise
-   *   GPOS will fail to correctly position the mark ligature on top of the
-   *   LAM,LAM,HEH ligature.  See:
-   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
-   *
-   * - If a ligature is formed of components that some of which are also ligatures
-   *   themselves, and those ligature components had marks attached to *their*
-   *   components, we have to attach the marks to the new ligature component
-   *   positions!  Now *that*'s tricky!  And these marks may be following the
-   *   last component of the whole sequence, so we should loop forward looking
-   *   for them and update them.
-   *
-   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
-   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
-   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
-   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
-   *   the new ligature with a component value of 2.
-   *
-   *   This in fact happened to a font...  See:
-   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
-   */
-
-  unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
-  unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer);
-  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-  unsigned int components_so_far = last_num_components;
-
-  if (!is_mark_ligature)
-  {
-    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
-    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
-    {
-      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
-    }
-  }
-  c->replace_glyph_with_ligature (lig_glyph, klass);
-
-  for (unsigned int i = 1; i < count; i++)
-  {
-    while (buffer->idx < match_positions[i] && buffer->successful)
-    {
-      if (!is_mark_ligature) {
-        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-        if (this_comp == 0)
-          this_comp = last_num_components;
-        unsigned int new_lig_comp = components_so_far - last_num_components +
-                                    MIN (this_comp, last_num_components);
-          _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
-      }
-      buffer->next_glyph ();
-    }
-
-    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-    components_so_far += last_num_components;
-
-    /* Skip the base glyph */
-    buffer->idx++;
-  }
-
-  if (!is_mark_ligature && last_lig_id) {
-    /* Re-adjust components for any marks following. */
-    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
-      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
-        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
-        if (!this_comp)
-          break;
-        unsigned int new_lig_comp = components_so_far - last_num_components +
-                                    MIN (this_comp, last_num_components);
-        _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
-      } else
-        break;
-    }
-  }
-  return_trace (true);
-}
-
-static inline bool match_backtrack (hb_ot_apply_context_t *c,
-                                    unsigned int count,
-                                    const HBUINT16 backtrack[],
-                                    match_func_t match_func,
-                                    const void *match_data,
-                                    unsigned int *match_start)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
-  skippy_iter.reset (c->buffer->backtrack_len (), count);
-  skippy_iter.set_match_func (match_func, match_data, backtrack);
-
-  for (unsigned int i = 0; i < count; i++)
-    if (!skippy_iter.prev ())
-      return_trace (false);
-
-  *match_start = skippy_iter.idx;
-
-  return_trace (true);
-}
-
-static inline bool match_lookahead (hb_ot_apply_context_t *c,
-                                    unsigned int count,
-                                    const HBUINT16 lookahead[],
-                                    match_func_t match_func,
-                                    const void *match_data,
-                                    unsigned int offset,
-                                    unsigned int *end_index)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
-  skippy_iter.reset (c->buffer->idx + offset - 1, count);
-  skippy_iter.set_match_func (match_func, match_data, lookahead);
-
-  for (unsigned int i = 0; i < count; i++)
-    if (!skippy_iter.next ())
-      return_trace (false);
-
-  *end_index = skippy_iter.idx + 1;
-
-  return_trace (true);
-}
-
-
-
-struct LookupRecord
-{
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
-  }
-
-  HBUINT16      sequenceIndex;          /* Index into current glyph
-                                         * sequence--first glyph = 0 */
-  HBUINT16      lookupListIndex;        /* Lookup to apply to that
-                                         * position--zero--based */
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
-template <typename context_t>
-static inline void recurse_lookups (context_t *c,
-                                    unsigned int lookupCount,
-                                    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
-{
-  for (unsigned int i = 0; i < lookupCount; i++)
-    c->recurse (lookupRecord[i].lookupListIndex);
-}
-
-static inline bool apply_lookup (hb_ot_apply_context_t *c,
-                                 unsigned int count, /* Including the first glyph */
-                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
-                                 unsigned int lookupCount,
-                                 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
-                                 unsigned int match_length)
-{
-  TRACE_APPLY (nullptr);
-
-  hb_buffer_t *buffer = c->buffer;
-  int end;
-
-  /* All positions are distance from beginning of *output* buffer.
-   * Adjust. */
-  {
-    unsigned int bl = buffer->backtrack_len ();
-    end = bl + match_length;
-
-    int delta = bl - buffer->idx;
-    /* Convert positions to new indexing. */
-    for (unsigned int j = 0; j < count; j++)
-      match_positions[j] += delta;
-  }
-
-  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
-  {
-    unsigned int idx = lookupRecord[i].sequenceIndex;
-    if (idx >= count)
-      continue;
-
-    /* Don't recurse to ourself at same position.
-     * Note that this test is too naive, it doesn't catch longer loops. */
-    if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
-      continue;
-
-    if (unlikely (!buffer->move_to (match_positions[idx])))
-      break;
-
-    if (unlikely (buffer->max_ops <= 0))
-      break;
-
-    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
-    if (!c->recurse (lookupRecord[i].lookupListIndex))
-      continue;
-
-    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
-    int delta = new_len - orig_len;
-
-    if (!delta)
-        continue;
-
-    /* Recursed lookup changed buffer len.  Adjust.
-     *
-     * TODO:
-     *
-     * Right now, if buffer length increased by n, we assume n new glyphs
-     * were added right after the current position, and if buffer length
-     * was decreased by n, we assume n match positions after the current
-     * one where removed.  The former (buffer length increased) case is
-     * fine, but the decrease case can be improved in at least two ways,
-     * both of which are significant:
-     *
-     *   - If recursed-to lookup is MultipleSubst and buffer length
-     *     decreased, then it's current match position that was deleted,
-     *     NOT the one after it.
-     *
-     *   - If buffer length was decreased by n, it does not necessarily
-     *     mean that n match positions where removed, as there might
-     *     have been marks and default-ignorables in the sequence.  We
-     *     should instead drop match positions between current-position
-     *     and current-position + n instead.
-     *
-     * It should be possible to construct tests for both of these cases.
-     */
-
-    end += delta;
-    if (end <= int (match_positions[idx]))
-    {
-      /* End might end up being smaller than match_positions[idx] if the recursed
-       * lookup ended up removing many items, more than we have had matched.
-       * Just never rewind end back and get out of here.
-       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
-      end = match_positions[idx];
-      /* There can't be any further changes. */
-      break;
-    }
-
-    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
-
-    if (delta > 0)
-    {
-      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
-        break;
-    }
-    else
-    {
-      /* NOTE: delta is negative. */
-      delta = MAX (delta, (int) next - (int) count);
-      next -= delta;
-    }
-
-    /* Shift! */
-    memmove (match_positions + next + delta, match_positions + next,
-             (count - next) * sizeof (match_positions[0]));
-    next += delta;
-    count += delta;
-
-    /* Fill in new entries. */
-    for (unsigned int j = idx + 1; j < next; j++)
-      match_positions[j] = match_positions[j - 1] + 1;
-
-    /* And fixup the rest. */
-    for (; next < count; next++)
-      match_positions[next] += delta;
-  }
-
-  buffer->move_to (end);
-
-  return_trace (true);
-}
-
-
-
-/* Contextual lookups */
-
-struct ContextClosureLookupContext
-{
-  ContextClosureFuncs funcs;
-  const void *intersects_data;
-};
-
-struct ContextCollectGlyphsLookupContext
-{
-  ContextCollectGlyphsFuncs funcs;
-  const void *collect_data;
-};
-
-struct ContextApplyLookupContext
-{
-  ContextApplyFuncs funcs;
-  const void *match_data;
-};
-
-static inline void context_closure_lookup (hb_closure_context_t *c,
-                                           unsigned int inputCount, /* Including the first glyph (not matched) */
-                                           const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                           unsigned int lookupCount,
-                                           const LookupRecord lookupRecord[],
-                                           ContextClosureLookupContext &lookup_context)
-{
-  if (intersects_array (c,
-                        inputCount ? inputCount - 1 : 0, input,
-                        lookup_context.funcs.intersects, lookup_context.intersects_data))
-    recurse_lookups (c,
-                     lookupCount, lookupRecord);
-}
-
-static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
-                                                  unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                  const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                  unsigned int lookupCount,
-                                                  const LookupRecord lookupRecord[],
-                                                  ContextCollectGlyphsLookupContext &lookup_context)
-{
-  collect_array (c, c->input,
-                 inputCount ? inputCount - 1 : 0, input,
-                 lookup_context.funcs.collect, lookup_context.collect_data);
-  recurse_lookups (c,
-                   lookupCount, lookupRecord);
-}
-
-static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
-                                               unsigned int inputCount, /* Including the first glyph (not matched) */
-                                               const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                               unsigned int lookupCount HB_UNUSED,
-                                               const LookupRecord lookupRecord[] HB_UNUSED,
-                                               ContextApplyLookupContext &lookup_context)
-{
-  return would_match_input (c,
-                            inputCount, input,
-                            lookup_context.funcs.match, lookup_context.match_data);
-}
-static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
-                                         unsigned int inputCount, /* Including the first glyph (not matched) */
-                                         const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                         unsigned int lookupCount,
-                                         const LookupRecord lookupRecord[],
-                                         ContextApplyLookupContext &lookup_context)
-{
-  unsigned int match_length = 0;
-  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-  return match_input (c,
-                      inputCount, input,
-                      lookup_context.funcs.match, lookup_context.match_data,
-                      &match_length, match_positions)
-      && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
-          apply_lookup (c,
-                       inputCount, match_positions,
-                       lookupCount, lookupRecord,
-                       match_length));
-}
-
-struct Rule
-{
-  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    context_closure_lookup (c,
-                            inputCount, inputZ,
-                            lookupCount, lookupRecord,
-                            lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    context_collect_glyphs_lookup (c,
-                                   inputCount, inputZ,
-                                   lookupCount, lookupRecord,
-                                   lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
-    return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
-  }
-
-  public:
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (inputCount.sanitize (c) &&
-                  lookupCount.sanitize (c) &&
-                  c->check_range (inputZ,
-                                  inputZ[0].static_size * inputCount +
-                                  LookupRecord::static_size * lookupCount));
-  }
-
-  protected:
-  HBUINT16      inputCount;             /* Total number of glyphs in input
-                                         * glyph sequence--includes the first
-                                         * glyph */
-  HBUINT16      lookupCount;            /* Number of LookupRecords */
-  HBUINT16      inputZ[VAR];            /* Array of match inputs--start with
-                                         * second glyph */
-/*LookupRecord  lookupRecordX[VAR];*/   /* Array of LookupRecords--in
-                                         * design order */
-  public:
-  DEFINE_SIZE_ARRAY (4, inputZ);
-};
-
-struct RuleSet
-{
-  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).closure (c, lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-    {
-      if ((this+rule[i]).would_apply (c, lookup_context))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-    {
-      if ((this+rule[i]).apply (c, lookup_context))
-        return_trace (true);
-    }
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rule.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<Rule>
-                rule;                   /* Array of Rule tables
-                                         * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, rule);
-};
-
-
-struct ContextFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-
-    const Coverage &cov = (this+coverage);
-
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
-      nullptr
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (cov.intersects_coverage (c->glyphs, i)) {
-        const RuleSet &rule_set = this+ruleSet[i];
-        rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_glyph},
-      nullptr
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      nullptr
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED))
-      return_trace (false);
-
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      nullptr
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-                coverage;               /* Offset to Coverage table--from
-                                         * beginning of table */
-  OffsetArrayOf<RuleSet>
-                ruleSet;                /* Array of RuleSet tables
-                                         * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ruleSet);
-};
-
-
-struct ContextFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverage).intersects (c->glyphs))
-      return;
-
-    const ClassDef &class_def = this+classDef;
-
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_class},
-      &class_def
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (class_def.intersects_class (c->glyphs, i)) {
-        const RuleSet &rule_set = this+ruleSet[i];
-        rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    const ClassDef &class_def = this+classDef;
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_class},
-      &class_def
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ClassDef &class_def = this+classDef;
-    unsigned int index = class_def.get_class (c->glyphs[0]);
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_class},
-      &class_def
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ClassDef &class_def = this+classDef;
-    index = class_def.get_class (c->buffer->cur().codepoint);
-    const RuleSet &rule_set = this+ruleSet[index];
-    struct ContextApplyLookupContext lookup_context = {
-      {match_class},
-      &class_def
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-                coverage;               /* Offset to Coverage table--from
-                                         * beginning of table */
-  OffsetTo<ClassDef>
-                classDef;               /* Offset to glyph ClassDef table--from
-                                         * beginning of table */
-  OffsetArrayOf<RuleSet>
-                ruleSet;                /* Array of RuleSet tables
-                                         * ordered by class */
-  public:
-  DEFINE_SIZE_ARRAY (8, ruleSet);
-};
-
-
-struct ContextFormat3
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverageZ[0]).intersects (c->glyphs))
-      return;
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
-      this
-    };
-    context_closure_lookup (c,
-                            glyphCount, (const HBUINT16 *) (coverageZ + 1),
-                            lookupCount, lookupRecord,
-                            lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverageZ[0]).add_coverage (c->input);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextCollectGlyphsLookupContext lookup_context = {
-      {collect_coverage},
-      this
-    };
-
-    context_collect_glyphs_lookup (c,
-                                   glyphCount, (const HBUINT16 *) (coverageZ + 1),
-                                   lookupCount, lookupRecord,
-                                   lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      this
-    };
-    return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverageZ[0];
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
-    struct ContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      this
-    };
-    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!c->check_struct (this)) return_trace (false);
-    unsigned int count = glyphCount;
-    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
-    if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
-    for (unsigned int i = 0; i < count; i++)
-      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
-    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
-    return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 3 */
-  HBUINT16      glyphCount;             /* Number of glyphs in the input glyph
-                                         * sequence */
-  HBUINT16      lookupCount;            /* Number of LookupRecords */
-  OffsetTo<Coverage>
-                coverageZ[VAR];         /* Array of offsets to Coverage
-                                         * table in glyph sequence order */
-/*LookupRecord  lookupRecordX[VAR];*/   /* Array of LookupRecords--in
-                                         * design order */
-  public:
-  DEFINE_SIZE_ARRAY (6, coverageZ);
-};
-
-struct Context
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  ContextFormat1        format1;
-  ContextFormat2        format2;
-  ContextFormat3        format3;
-  } u;
-};
-
-
-/* Chaining Contextual lookups */
-
-struct ChainContextClosureLookupContext
-{
-  ContextClosureFuncs funcs;
-  const void *intersects_data[3];
-};
-
-struct ChainContextCollectGlyphsLookupContext
-{
-  ContextCollectGlyphsFuncs funcs;
-  const void *collect_data[3];
-};
-
-struct ChainContextApplyLookupContext
-{
-  ContextApplyFuncs funcs;
-  const void *match_data[3];
-};
-
-static inline void chain_context_closure_lookup (hb_closure_context_t *c,
-                                                 unsigned int backtrackCount,
-                                                 const HBUINT16 backtrack[],
-                                                 unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                 const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                 unsigned int lookaheadCount,
-                                                 const HBUINT16 lookahead[],
-                                                 unsigned int lookupCount,
-                                                 const LookupRecord lookupRecord[],
-                                                 ChainContextClosureLookupContext &lookup_context)
-{
-  if (intersects_array (c,
-                        backtrackCount, backtrack,
-                        lookup_context.funcs.intersects, lookup_context.intersects_data[0])
-   && intersects_array (c,
-                        inputCount ? inputCount - 1 : 0, input,
-                        lookup_context.funcs.intersects, lookup_context.intersects_data[1])
-   && intersects_array (c,
-                       lookaheadCount, lookahead,
-                       lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
-    recurse_lookups (c,
-                     lookupCount, lookupRecord);
-}
-
-static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
-                                                        unsigned int backtrackCount,
-                                                        const HBUINT16 backtrack[],
-                                                        unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                        const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                        unsigned int lookaheadCount,
-                                                        const HBUINT16 lookahead[],
-                                                        unsigned int lookupCount,
-                                                        const LookupRecord lookupRecord[],
-                                                        ChainContextCollectGlyphsLookupContext &lookup_context)
-{
-  collect_array (c, c->before,
-                 backtrackCount, backtrack,
-                 lookup_context.funcs.collect, lookup_context.collect_data[0]);
-  collect_array (c, c->input,
-                 inputCount ? inputCount - 1 : 0, input,
-                 lookup_context.funcs.collect, lookup_context.collect_data[1]);
-  collect_array (c, c->after,
-                 lookaheadCount, lookahead,
-                 lookup_context.funcs.collect, lookup_context.collect_data[2]);
-  recurse_lookups (c,
-                   lookupCount, lookupRecord);
-}
-
-static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
-                                                     unsigned int backtrackCount,
-                                                     const HBUINT16 backtrack[] HB_UNUSED,
-                                                     unsigned int inputCount, /* Including the first glyph (not matched) */
-                                                     const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                                     unsigned int lookaheadCount,
-                                                     const HBUINT16 lookahead[] HB_UNUSED,
-                                                     unsigned int lookupCount HB_UNUSED,
-                                                     const LookupRecord lookupRecord[] HB_UNUSED,
-                                                     ChainContextApplyLookupContext &lookup_context)
-{
-  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
-      && would_match_input (c,
-                            inputCount, input,
-                            lookup_context.funcs.match, lookup_context.match_data[1]);
-}
-
-static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
-                                               unsigned int backtrackCount,
-                                               const HBUINT16 backtrack[],
-                                               unsigned int inputCount, /* Including the first glyph (not matched) */
-                                               const HBUINT16 input[], /* Array of input values--start with second glyph */
-                                               unsigned int lookaheadCount,
-                                               const HBUINT16 lookahead[],
-                                               unsigned int lookupCount,
-                                               const LookupRecord lookupRecord[],
-                                               ChainContextApplyLookupContext &lookup_context)
-{
-  unsigned int start_index = 0, match_length = 0, end_index = 0;
-  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-  return match_input (c,
-                      inputCount, input,
-                      lookup_context.funcs.match, lookup_context.match_data[1],
-                      &match_length, match_positions)
-      && match_backtrack (c,
-                          backtrackCount, backtrack,
-                          lookup_context.funcs.match, lookup_context.match_data[0],
-                          &start_index)
-      && match_lookahead (c,
-                          lookaheadCount, lookahead,
-                          lookup_context.funcs.match, lookup_context.match_data[2],
-                          match_length, &end_index)
-      && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
-          apply_lookup (c,
-                       inputCount, match_positions,
-                       lookupCount, lookupRecord,
-                       match_length));
-}
-
-struct ChainRule
-{
-  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    chain_context_closure_lookup (c,
-                                  backtrack.len, backtrack.arrayZ,
-                                  input.len, input.arrayZ,
-                                  lookahead.len, lookahead.arrayZ,
-                                  lookup.len, lookup.arrayZ,
-                                  lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    chain_context_collect_glyphs_lookup (c,
-                                         backtrack.len, backtrack.arrayZ,
-                                         input.len, input.arrayZ,
-                                         lookahead.len, lookahead.arrayZ,
-                                         lookup.len, lookup.arrayZ,
-                                         lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (chain_context_would_apply_lookup (c,
-                                                    backtrack.len, backtrack.arrayZ,
-                                                    input.len, input.arrayZ,
-                                                    lookahead.len, lookahead.arrayZ, lookup.len,
-                                                    lookup.arrayZ, lookup_context));
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (chain_context_apply_lookup (c,
-                                              backtrack.len, backtrack.arrayZ,
-                                              input.len, input.arrayZ,
-                                              lookahead.len, lookahead.arrayZ, lookup.len,
-                                              lookup.arrayZ, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c)) return_trace (false);
-    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-    if (!input.sanitize (c)) return_trace (false);
-    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-    if (!lookahead.sanitize (c)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (lookup.sanitize (c));
-  }
-
-  protected:
-  ArrayOf<HBUINT16>
-                backtrack;              /* Array of backtracking values
-                                         * (to be matched before the input
-                                         * sequence) */
-  HeadlessArrayOf<HBUINT16>
-                inputX;                 /* Array of input values (start with
-                                         * second glyph) */
-  ArrayOf<HBUINT16>
-                lookaheadX;             /* Array of lookahead values's (to be
-                                         * matched after the input sequence) */
-  ArrayOf<LookupRecord>
-                lookupX;                /* Array of LookupRecords--in
-                                         * design order) */
-  public:
-  DEFINE_SIZE_MIN (8);
-};
-
-struct ChainRuleSet
-{
-  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-  {
-    TRACE_CLOSURE (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).closure (c, lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      (this+rule[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_WOULD_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      if ((this+rule[i]).would_apply (c, lookup_context))
-        return_trace (true);
-
-    return_trace (false);
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-  {
-    TRACE_APPLY (this);
-    unsigned int num_rules = rule.len;
-    for (unsigned int i = 0; i < num_rules; i++)
-      if ((this+rule[i]).apply (c, lookup_context))
-        return_trace (true);
-
-    return_trace (false);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (rule.sanitize (c, this));
-  }
-
-  protected:
-  OffsetArrayOf<ChainRule>
-                rule;                   /* Array of ChainRule tables
-                                         * ordered by preference */
-  public:
-  DEFINE_SIZE_ARRAY (2, rule);
-};
-
-struct ChainContextFormat1
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const Coverage &cov = (this+coverage);
-
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (cov.intersects_coverage (c->glyphs, i)) {
-        const ChainRuleSet &rule_set = this+ruleSet[i];
-        rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_glyph},
-      {nullptr, nullptr, nullptr}
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 1 */
-  OffsetTo<Coverage>
-                coverage;               /* Offset to Coverage table--from
-                                         * beginning of table */
-  OffsetArrayOf<ChainRuleSet>
-                ruleSet;                /* Array of ChainRuleSet tables
-                                         * ordered by Coverage Index */
-  public:
-  DEFINE_SIZE_ARRAY (6, ruleSet);
-};
-
-struct ChainContextFormat2
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    if (!(this+coverage).intersects (c->glyphs))
-      return;
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (input_class_def.intersects_class (c->glyphs, i)) {
-        const ChainRuleSet &rule_set = this+ruleSet[i];
-        rule_set.closure (c, lookup_context);
-      }
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    (this+coverage).add_coverage (c->input);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-
-    unsigned int count = ruleSet.len;
-    for (unsigned int i = 0; i < count; i++)
-      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    unsigned int index = input_class_def.get_class (c->glyphs[0]);
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-    return_trace (rule_set.would_apply (c, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    return this+coverage;
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const ClassDef &backtrack_class_def = this+backtrackClassDef;
-    const ClassDef &input_class_def = this+inputClassDef;
-    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
-
-    index = input_class_def.get_class (c->buffer->cur().codepoint);
-    const ChainRuleSet &rule_set = this+ruleSet[index];
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_class},
-      {&backtrack_class_def,
-       &input_class_def,
-       &lookahead_class_def}
-    };
-    return_trace (rule_set.apply (c, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (coverage.sanitize (c, this) &&
-                  backtrackClassDef.sanitize (c, this) &&
-                  inputClassDef.sanitize (c, this) &&
-                  lookaheadClassDef.sanitize (c, this) &&
-                  ruleSet.sanitize (c, this));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 2 */
-  OffsetTo<Coverage>
-                coverage;               /* Offset to Coverage table--from
-                                         * beginning of table */
-  OffsetTo<ClassDef>
-                backtrackClassDef;      /* Offset to glyph ClassDef table
-                                         * containing backtrack sequence
-                                         * data--from beginning of table */
-  OffsetTo<ClassDef>
-                inputClassDef;          /* Offset to glyph ClassDef
-                                         * table containing input sequence
-                                         * data--from beginning of table */
-  OffsetTo<ClassDef>
-                lookaheadClassDef;      /* Offset to glyph ClassDef table
-                                         * containing lookahead sequence
-                                         * data--from beginning of table */
-  OffsetArrayOf<ChainRuleSet>
-                ruleSet;                /* Array of ChainRuleSet tables
-                                         * ordered by class */
-  public:
-  DEFINE_SIZE_ARRAY (12, ruleSet);
-};
-
-struct ChainContextFormat3
-{
-  inline void closure (hb_closure_context_t *c) const
-  {
-    TRACE_CLOSURE (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    if (!(this+input[0]).intersects (c->glyphs))
-      return;
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextClosureLookupContext lookup_context = {
-      {intersects_coverage},
-      {this, this, this}
-    };
-    chain_context_closure_lookup (c,
-                                  backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                  input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                  lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                  lookup.len, lookup.arrayZ,
-                                  lookup_context);
-  }
-
-  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
-  {
-    TRACE_COLLECT_GLYPHS (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    (this+input[0]).add_coverage (c->input);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextCollectGlyphsLookupContext lookup_context = {
-      {collect_coverage},
-      {this, this, this}
-    };
-    chain_context_collect_glyphs_lookup (c,
-                                         backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                         input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                         lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                         lookup.len, lookup.arrayZ,
-                                         lookup_context);
-  }
-
-  inline bool would_apply (hb_would_apply_context_t *c) const
-  {
-    TRACE_WOULD_APPLY (this);
-
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      {this, this, this}
-    };
-    return_trace (chain_context_would_apply_lookup (c,
-                                                    backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                                    input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                                    lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                                    lookup.len, lookup.arrayZ, lookup_context));
-  }
-
-  inline const Coverage &get_coverage (void) const
-  {
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    return this+input[0];
-  }
-
-  inline bool apply (hb_ot_apply_context_t *c) const
-  {
-    TRACE_APPLY (this);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-
-    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
-    if (likely (index == NOT_COVERED)) return_trace (false);
-
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    struct ChainContextApplyLookupContext lookup_context = {
-      {match_coverage},
-      {this, this, this}
-    };
-    return_trace (chain_context_apply_lookup (c,
-                                              backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-                                              input.len, (const HBUINT16 *) input.arrayZ + 1,
-                                              lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-                                              lookup.len, lookup.arrayZ, lookup_context));
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (!backtrack.sanitize (c, this)) return_trace (false);
-    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-    if (!input.sanitize (c, this)) return_trace (false);
-    if (!input.len) return_trace (false); /* To be consistent with Context. */
-    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-    if (!lookahead.sanitize (c, this)) return_trace (false);
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-    return_trace (lookup.sanitize (c));
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier--format = 3 */
-  OffsetArrayOf<Coverage>
-                backtrack;              /* Array of coverage tables
-                                         * in backtracking sequence, in  glyph
-                                         * sequence order */
-  OffsetArrayOf<Coverage>
-                inputX          ;       /* Array of coverage
-                                         * tables in input sequence, in glyph
-                                         * sequence order */
-  OffsetArrayOf<Coverage>
-                lookaheadX;             /* Array of coverage tables
-                                         * in lookahead sequence, in glyph
-                                         * sequence order */
-  ArrayOf<LookupRecord>
-                lookupX;                /* Array of LookupRecords--in
-                                         * design order) */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-struct ChainContext
-{
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (c->dispatch (u.format1));
-    case 2: return_trace (c->dispatch (u.format2));
-    case 3: return_trace (c->dispatch (u.format3));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format; /* Format identifier */
-  ChainContextFormat1   format1;
-  ChainContextFormat2   format2;
-  ChainContextFormat3   format3;
-  } u;
-};
-
-
-template <typename T>
-struct ExtensionFormat1
-{
-  inline unsigned int get_type (void) const { return extensionLookupType; }
-
-  template <typename X>
-  inline const X& get_subtable (void) const
-  {
-    unsigned int offset = extensionOffset;
-    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
-    return StructAtOffset<typename T::LookupSubTable> (this, offset);
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, format);
-    if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
-    return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
-  }
-
-  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-                  extensionOffset != 0 &&
-                  extensionLookupType != T::LookupSubTable::Extension);
-  }
-
-  protected:
-  HBUINT16      format;                 /* Format identifier. Set to 1. */
-  HBUINT16      extensionLookupType;    /* Lookup type of subtable referenced
-                                         * by ExtensionOffset (i.e. the
-                                         * extension subtable). */
-  HBUINT32      extensionOffset;        /* Offset to the extension subtable,
-                                         * of lookup type subtable. */
-  public:
-  DEFINE_SIZE_STATIC (8);
-};
-
-template <typename T>
-struct Extension
-{
-  inline unsigned int get_type (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.get_type ();
-    default:return 0;
-    }
-  }
-  template <typename X>
-  inline const X& get_subtable (void) const
-  {
-    switch (u.format) {
-    case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
-    default:return Null(typename T::LookupSubTable);
-    }
-  }
-
-  template <typename context_t>
-  inline typename context_t::return_t dispatch (context_t *c) const
-  {
-    TRACE_DISPATCH (this, u.format);
-    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-    switch (u.format) {
-    case 1: return_trace (u.format1.dispatch (c));
-    default:return_trace (c->default_return_value ());
-    }
-  }
-
-  protected:
-  union {
-  HBUINT16              format;         /* Format identifier */
-  ExtensionFormat1<T>   format1;
-  } u;
-};
-
-
-/*
- * GSUB/GPOS Common
- */
-
-struct GSUBGPOS
-{
-  inline unsigned int get_script_count (void) const
-  { return (this+scriptList).len; }
-  inline const Tag& get_script_tag (unsigned int i) const
-  { return (this+scriptList).get_tag (i); }
-  inline unsigned int get_script_tags (unsigned int start_offset,
-                                       unsigned int *script_count /* IN/OUT */,
-                                       hb_tag_t     *script_tags /* OUT */) const
-  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
-  inline const Script& get_script (unsigned int i) const
-  { return (this+scriptList)[i]; }
-  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+scriptList).find_index (tag, index); }
-
-  inline unsigned int get_feature_count (void) const
-  { return (this+featureList).len; }
-  inline hb_tag_t get_feature_tag (unsigned int i) const
-  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
-  inline unsigned int get_feature_tags (unsigned int start_offset,
-                                        unsigned int *feature_count /* IN/OUT */,
-                                        hb_tag_t     *feature_tags /* OUT */) const
-  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
-  inline const Feature& get_feature (unsigned int i) const
-  { return (this+featureList)[i]; }
-  inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
-  { return (this+featureList).find_index (tag, index); }
-
-  inline unsigned int get_lookup_count (void) const
-  { return (this+lookupList).len; }
-  inline const Lookup& get_lookup (unsigned int i) const
-  { return (this+lookupList)[i]; }
-
-  inline bool find_variations_index (const int *coords, unsigned int num_coords,
-                                     unsigned int *index) const
-  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
-           .find_index (coords, num_coords, index); }
-  inline const Feature& get_feature_variation (unsigned int feature_index,
-                                               unsigned int variations_index) const
-  {
-    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
-        version.to_int () >= 0x00010001u)
-    {
-      const Feature *feature = (this+featureVars).find_substitute (variations_index,
-                                                                   feature_index);
-      if (feature)
-        return *feature;
-    }
-    return get_feature (feature_index);
-  }
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-                  likely (version.major == 1) &&
-                  scriptList.sanitize (c, this) &&
-                  featureList.sanitize (c, this) &&
-                  lookupList.sanitize (c, this) &&
-                  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
-  }
-
-  protected:
-  FixedVersion<>version;        /* Version of the GSUB/GPOS table--initially set
-                                 * to 0x00010000u */
-  OffsetTo<ScriptList>
-                scriptList;     /* ScriptList table */
-  OffsetTo<FeatureList>
-                featureList;    /* FeatureList table */
-  OffsetTo<LookupList>
-                lookupList;     /* LookupList table */
-  LOffsetTo<FeatureVariations>
-                featureVars;    /* Offset to Feature Variations
-                                   table--from beginning of table
-                                 * (may be NULL).  Introduced
-                                 * in version 0x00010001. */
-  public:
-  DEFINE_SIZE_MIN (10);
-};
-
-
-} /* namespace OT */
-
-
-#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-gsubgpos.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,2779 @@
+/*
+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
+ * Copyright © 2010,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_LAYOUT_GSUBGPOS_HH
+#define HB_OT_LAYOUT_GSUBGPOS_HH
+
+#include "hb.hh"
+#include "hb-buffer.hh"
+#include "hb-map.hh"
+#include "hb-set.hh"
+#include "hb-ot-map.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-layout-gdef-table.hh"
+
+
+namespace OT {
+
+
+struct hb_intersects_context_t :
+       hb_dispatch_context_t<hb_intersects_context_t, bool, 0>
+{
+  const char *get_name () { return "INTERSECTS"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.intersects (this->glyphs); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  const hb_set_t *glyphs;
+  unsigned int debug_depth;
+
+  hb_intersects_context_t (const hb_set_t *glyphs_) :
+                             glyphs (glyphs_),
+                             debug_depth (0) {}
+};
+
+struct hb_closure_context_t :
+       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, 0>
+{
+  const char *get_name () { return "CLOSURE"; }
+  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
+  static return_t default_return_value () { return HB_VOID; }
+  void recurse (unsigned int lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func))
+      return;
+
+    nesting_level_left--;
+    recurse_func (this, lookup_index);
+    nesting_level_left++;
+  }
+
+  bool should_visit_lookup (unsigned int lookup_index)
+  {
+    if (is_lookup_done (lookup_index))
+      return false;
+    done_lookups->set (lookup_index, glyphs->get_population ());
+    return true;
+  }
+
+  bool is_lookup_done (unsigned int lookup_index)
+  {
+    /* Have we visited this lookup with the current set of glyphs? */
+    return done_lookups->get (lookup_index) == glyphs->get_population ();
+  }
+
+  hb_face_t *face;
+  hb_set_t *glyphs;
+  hb_set_t out[1];
+  recurse_func_t recurse_func;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  hb_closure_context_t (hb_face_t *face_,
+                        hb_set_t *glyphs_,
+                        hb_map_t *done_lookups_,
+                        unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
+                          face (face_),
+                          glyphs (glyphs_),
+                          recurse_func (nullptr),
+                          nesting_level_left (nesting_level_left_),
+                          debug_depth (0),
+                          done_lookups (done_lookups_) {}
+
+  ~hb_closure_context_t () { flush (); }
+
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+
+  void flush ()
+  {
+    hb_set_union (glyphs, out);
+    hb_set_clear (out);
+  }
+
+  private:
+  hb_map_t *done_lookups;
+};
+
+
+struct hb_would_apply_context_t :
+       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
+{
+  const char *get_name () { return "WOULD_APPLY"; }
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.would_apply (this); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+
+  hb_face_t *face;
+  const hb_codepoint_t *glyphs;
+  unsigned int len;
+  bool zero_context;
+  unsigned int debug_depth;
+
+  hb_would_apply_context_t (hb_face_t *face_,
+                            const hb_codepoint_t *glyphs_,
+                            unsigned int len_,
+                            bool zero_context_) :
+                              face (face_),
+                              glyphs (glyphs_),
+                              len (len_),
+                              zero_context (zero_context_),
+                              debug_depth (0) {}
+};
+
+
+struct hb_collect_glyphs_context_t :
+       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, 0>
+{
+  const char *get_name () { return "COLLECT_GLYPHS"; }
+  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
+  static return_t default_return_value () { return HB_VOID; }
+  void recurse (unsigned int lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func))
+      return;
+
+    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
+     * past the previous check.  For GSUB, we only want to collect the output
+     * glyphs in the recursion.  If output is not requested, we can go home now.
+     *
+     * Note further, that the above is not exactly correct.  A recursed lookup
+     * is allowed to match input that is not matched in the context, but that's
+     * not how most fonts are built.  It's possible to relax that and recurse
+     * with all sets here if it proves to be an issue.
+     */
+
+    if (output == hb_set_get_empty ())
+      return;
+
+    /* Return if new lookup was recursed to before. */
+    if (recursed_lookups->has (lookup_index))
+      return;
+
+    hb_set_t *old_before = before;
+    hb_set_t *old_input  = input;
+    hb_set_t *old_after  = after;
+    before = input = after = hb_set_get_empty ();
+
+    nesting_level_left--;
+    recurse_func (this, lookup_index);
+    nesting_level_left++;
+
+    before = old_before;
+    input  = old_input;
+    after  = old_after;
+
+    recursed_lookups->add (lookup_index);
+  }
+
+  hb_face_t *face;
+  hb_set_t *before;
+  hb_set_t *input;
+  hb_set_t *after;
+  hb_set_t *output;
+  recurse_func_t recurse_func;
+  hb_set_t *recursed_lookups;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  hb_collect_glyphs_context_t (hb_face_t *face_,
+                               hb_set_t  *glyphs_before, /* OUT.  May be NULL */
+                               hb_set_t  *glyphs_input,  /* OUT.  May be NULL */
+                               hb_set_t  *glyphs_after,  /* OUT.  May be NULL */
+                               hb_set_t  *glyphs_output, /* OUT.  May be NULL */
+                               unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
+                              face (face_),
+                              before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
+                              input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
+                              after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
+                              output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
+                              recurse_func (nullptr),
+                              recursed_lookups (hb_set_create ()),
+                              nesting_level_left (nesting_level_left_),
+                              debug_depth (0) {}
+  ~hb_collect_glyphs_context_t () { hb_set_destroy (recursed_lookups); }
+
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+};
+
+
+
+template <typename set_t>
+struct hb_add_coverage_context_t :
+       hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
+{
+  const char *get_name () { return "GET_COVERAGE"; }
+  typedef const Coverage &return_t;
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.get_coverage (); }
+  static return_t default_return_value () { return Null(Coverage); }
+  bool stop_sublookup_iteration (return_t r) const
+  {
+    r.add_coverage (set);
+    return false;
+  }
+
+  hb_add_coverage_context_t (set_t *set_) :
+                            set (set_),
+                            debug_depth (0) {}
+
+  set_t *set;
+  unsigned int debug_depth;
+};
+
+
+struct hb_ot_apply_context_t :
+       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
+{
+  struct matcher_t
+  {
+    matcher_t () :
+             lookup_props (0),
+             ignore_zwnj (false),
+             ignore_zwj (false),
+             mask (-1),
+#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
+             syllable arg1(0),
+#undef arg1
+             match_func (nullptr),
+             match_data (nullptr) {}
+
+    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+
+    void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
+    void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
+    void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
+    void set_mask (hb_mask_t mask_) { mask = mask_; }
+    void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
+    void set_match_func (match_func_t match_func_,
+                                const void *match_data_)
+    { match_func = match_func_; match_data = match_data_; }
+
+    enum may_match_t {
+      MATCH_NO,
+      MATCH_YES,
+      MATCH_MAYBE
+    };
+
+    may_match_t may_match (const hb_glyph_info_t &info,
+                                  const HBUINT16        *glyph_data) const
+    {
+      if (!(info.mask & mask) ||
+          (syllable && syllable != info.syllable ()))
+        return MATCH_NO;
+
+      if (match_func)
+        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
+
+      return MATCH_MAYBE;
+    }
+
+    enum may_skip_t {
+      SKIP_NO,
+      SKIP_YES,
+      SKIP_MAYBE
+    };
+
+    may_skip_t may_skip (const hb_ot_apply_context_t *c,
+                         const hb_glyph_info_t       &info) const
+    {
+      if (!c->check_glyph_property (&info, lookup_props))
+        return SKIP_YES;
+
+      if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
+                    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
+                    (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
+        return SKIP_MAYBE;
+
+      return SKIP_NO;
+    }
+
+    protected:
+    unsigned int lookup_props;
+    bool ignore_zwnj;
+    bool ignore_zwj;
+    hb_mask_t mask;
+    uint8_t syllable;
+    match_func_t match_func;
+    const void *match_data;
+  };
+
+  struct skipping_iterator_t
+  {
+    void init (hb_ot_apply_context_t *c_, bool context_match = false)
+    {
+      c = c_;
+      match_glyph_data = nullptr;
+      matcher.set_match_func (nullptr, nullptr);
+      matcher.set_lookup_props (c->lookup_props);
+      /* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
+      matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
+      /* Ignore ZWJ if we are matching context, or asked to. */
+      matcher.set_ignore_zwj  (context_match || c->auto_zwj);
+      matcher.set_mask (context_match ? -1 : c->lookup_mask);
+    }
+    void set_lookup_props (unsigned int lookup_props)
+    {
+      matcher.set_lookup_props (lookup_props);
+    }
+    void set_match_func (matcher_t::match_func_t match_func_,
+                         const void *match_data_,
+                         const HBUINT16 glyph_data[])
+    {
+      matcher.set_match_func (match_func_, match_data_);
+      match_glyph_data = glyph_data;
+    }
+
+    void reset (unsigned int start_index_,
+                       unsigned int num_items_)
+    {
+      idx = start_index_;
+      num_items = num_items_;
+      end = c->buffer->len;
+      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
+    }
+
+    void reject () { num_items++; match_glyph_data--; }
+
+    matcher_t::may_skip_t
+    may_skip (const hb_glyph_info_t &info) const
+    { return matcher.may_skip (c, info); }
+
+    bool next ()
+    {
+      assert (num_items > 0);
+      while (idx + num_items < end)
+      {
+        idx++;
+        const hb_glyph_info_t &info = c->buffer->info[idx];
+
+        matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+        if (unlikely (skip == matcher_t::SKIP_YES))
+          continue;
+
+        matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+        if (match == matcher_t::MATCH_YES ||
+            (match == matcher_t::MATCH_MAYBE &&
+             skip == matcher_t::SKIP_NO))
+        {
+          num_items--;
+          match_glyph_data++;
+          return true;
+        }
+
+        if (skip == matcher_t::SKIP_NO)
+          return false;
+      }
+      return false;
+    }
+    bool prev ()
+    {
+      assert (num_items > 0);
+      while (idx > num_items - 1)
+      {
+        idx--;
+        const hb_glyph_info_t &info = c->buffer->out_info[idx];
+
+        matcher_t::may_skip_t skip = matcher.may_skip (c, info);
+        if (unlikely (skip == matcher_t::SKIP_YES))
+          continue;
+
+        matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+        if (match == matcher_t::MATCH_YES ||
+            (match == matcher_t::MATCH_MAYBE &&
+             skip == matcher_t::SKIP_NO))
+        {
+          num_items--;
+          match_glyph_data++;
+          return true;
+        }
+
+        if (skip == matcher_t::SKIP_NO)
+          return false;
+      }
+      return false;
+    }
+
+    unsigned int idx;
+    protected:
+    hb_ot_apply_context_t *c;
+    matcher_t matcher;
+    const HBUINT16 *match_glyph_data;
+
+    unsigned int num_items;
+    unsigned int end;
+  };
+
+
+  const char *get_name () { return "APPLY"; }
+  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
+  template <typename T>
+  return_t dispatch (const T &obj) { return obj.apply (this); }
+  static return_t default_return_value () { return false; }
+  bool stop_sublookup_iteration (return_t r) const { return r; }
+  return_t recurse (unsigned int sub_lookup_index)
+  {
+    if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
+      return default_return_value ();
+
+    nesting_level_left--;
+    bool ret = recurse_func (this, sub_lookup_index);
+    nesting_level_left++;
+    return ret;
+  }
+
+  skipping_iterator_t iter_input, iter_context;
+
+  hb_font_t *font;
+  hb_face_t *face;
+  hb_buffer_t *buffer;
+  recurse_func_t recurse_func;
+  const GDEF &gdef;
+  const VariationStore &var_store;
+
+  hb_direction_t direction;
+  hb_mask_t lookup_mask;
+  unsigned int table_index; /* GSUB/GPOS */
+  unsigned int lookup_index;
+  unsigned int lookup_props;
+  unsigned int nesting_level_left;
+  unsigned int debug_depth;
+
+  bool has_glyph_classes;
+  bool auto_zwnj;
+  bool auto_zwj;
+  bool random;
+
+  uint32_t random_state;
+
+
+  hb_ot_apply_context_t (unsigned int table_index_,
+                      hb_font_t *font_,
+                      hb_buffer_t *buffer_) :
+                        iter_input (), iter_context (),
+                        font (font_), face (font->face), buffer (buffer_),
+                        recurse_func (nullptr),
+                        gdef (*face->table.GDEF->table),
+                        var_store (gdef.get_var_store ()),
+                        direction (buffer_->props.direction),
+                        lookup_mask (1),
+                        table_index (table_index_),
+                        lookup_index ((unsigned int) -1),
+                        lookup_props (0),
+                        nesting_level_left (HB_MAX_NESTING_LEVEL),
+                        debug_depth (0),
+                        has_glyph_classes (gdef.has_glyph_classes ()),
+                        auto_zwnj (true),
+                        auto_zwj (true),
+                        random (false),
+                        random_state (1) { init_iters (); }
+
+  void init_iters ()
+  {
+    iter_input.init (this, false);
+    iter_context.init (this, true);
+  }
+
+  void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
+  void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
+  void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
+  void set_random (bool random_) { random = random_; }
+  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
+  void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
+  void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; init_iters (); }
+
+  uint32_t random_number ()
+  {
+    /* http://www.cplusplus.com/reference/random/minstd_rand/ */
+    random_state = random_state * 48271 % 2147483647;
+    return random_state;
+  }
+
+  bool match_properties_mark (hb_codepoint_t  glyph,
+                              unsigned int    glyph_props,
+                              unsigned int    match_props) const
+  {
+    /* If using mark filtering sets, the high short of
+     * match_props has the set index.
+     */
+    if (match_props & LookupFlag::UseMarkFilteringSet)
+      return gdef.mark_set_covers (match_props >> 16, glyph);
+
+    /* The second byte of match_props has the meaning
+     * "ignore marks of attachment type different than
+     * the attachment type specified."
+     */
+    if (match_props & LookupFlag::MarkAttachmentType)
+      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
+
+    return true;
+  }
+
+  bool check_glyph_property (const hb_glyph_info_t *info,
+                             unsigned int  match_props) const
+  {
+    hb_codepoint_t glyph = info->codepoint;
+    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
+
+    /* Not covered, if, for example, glyph class is ligature and
+     * match_props includes LookupFlags::IgnoreLigatures
+     */
+    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
+      return false;
+
+    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
+      return match_properties_mark (glyph, glyph_props, match_props);
+
+    return true;
+  }
+
+  void _set_glyph_props (hb_codepoint_t glyph_index,
+                          unsigned int class_guess = 0,
+                          bool ligature = false,
+                          bool component = false) const
+  {
+    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
+                          HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
+    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
+    if (ligature)
+    {
+      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
+      /* In the only place that the MULTIPLIED bit is used, Uniscribe
+       * seems to only care about the "last" transformation between
+       * Ligature and Multiple substitutions.  Ie. if you ligate, expand,
+       * and ligate again, it forgives the multiplication and acts as
+       * if only ligation happened.  As such, clear MULTIPLIED bit.
+       */
+      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+    }
+    if (component)
+      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
+    if (likely (has_glyph_classes))
+      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
+    else if (class_guess)
+      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
+  }
+
+  void replace_glyph (hb_codepoint_t glyph_index) const
+  {
+    _set_glyph_props (glyph_index);
+    buffer->replace_glyph (glyph_index);
+  }
+  void replace_glyph_inplace (hb_codepoint_t glyph_index) const
+  {
+    _set_glyph_props (glyph_index);
+    buffer->cur().codepoint = glyph_index;
+  }
+  void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
+                                           unsigned int class_guess) const
+  {
+    _set_glyph_props (glyph_index, class_guess, true);
+    buffer->replace_glyph (glyph_index);
+  }
+  void output_glyph_for_component (hb_codepoint_t glyph_index,
+                                          unsigned int class_guess) const
+  {
+    _set_glyph_props (glyph_index, class_guess, false, true);
+    buffer->output_glyph (glyph_index);
+  }
+};
+
+
+struct hb_get_subtables_context_t :
+       hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
+{
+  template <typename Type>
+  static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
+  {
+    const Type *typed_obj = (const Type *) obj;
+    return typed_obj->apply (c);
+  }
+
+  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
+
+  struct hb_applicable_t
+  {
+    template <typename T>
+    void init (const T &obj_, hb_apply_func_t apply_func_)
+    {
+      obj = &obj_;
+      apply_func = apply_func_;
+      digest.init ();
+      obj_.get_coverage ().add_coverage (&digest);
+    }
+
+    bool apply (OT::hb_ot_apply_context_t *c) const
+    {
+      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
+    }
+
+    private:
+    const void *obj;
+    hb_apply_func_t apply_func;
+    hb_set_digest_t digest;
+  };
+
+  typedef hb_vector_t<hb_applicable_t> array_t;
+
+  /* Dispatch interface. */
+  const char *get_name () { return "GET_SUBTABLES"; }
+  template <typename T>
+  return_t dispatch (const T &obj)
+  {
+    hb_applicable_t *entry = array.push();
+    entry->init (obj, apply_to<T>);
+    return HB_VOID;
+  }
+  static return_t default_return_value () { return HB_VOID; }
+
+  hb_get_subtables_context_t (array_t &array_) :
+                              array (array_),
+                              debug_depth (0) {}
+
+  array_t &array;
+  unsigned int debug_depth;
+};
+
+
+
+
+typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
+typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
+typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+
+struct ContextClosureFuncs
+{
+  intersects_func_t intersects;
+};
+struct ContextCollectGlyphsFuncs
+{
+  collect_glyphs_func_t collect;
+};
+struct ContextApplyFuncs
+{
+  match_func_t match;
+};
+
+
+static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  return glyphs->has (value);
+}
+static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return class_def.intersects_class (glyphs, value);
+}
+static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  return (data+coverage).intersects (glyphs);
+}
+
+static inline bool intersects_array (const hb_set_t *glyphs,
+                                     unsigned int count,
+                                     const HBUINT16 values[],
+                                     intersects_func_t intersects_func,
+                                     const void *intersects_data)
+{
+  for (unsigned int i = 0; i < count; i++)
+    if (likely (!intersects_func (glyphs, values[i], intersects_data)))
+      return false;
+  return true;
+}
+
+
+static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  glyphs->add (value);
+}
+static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  class_def.add_class (glyphs, value);
+}
+static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  (data+coverage).add_coverage (glyphs);
+}
+static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
+                                  hb_set_t *glyphs,
+                                  unsigned int count,
+                                  const HBUINT16 values[],
+                                  collect_glyphs_func_t collect_func,
+                                  const void *collect_data)
+{
+  for (unsigned int i = 0; i < count; i++)
+    collect_func (glyphs, values[i], collect_data);
+}
+
+
+static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
+{
+  return glyph_id == value;
+}
+static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+{
+  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+  return class_def.get_class (glyph_id) == value;
+}
+static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+{
+  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
+  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
+}
+
+static inline bool would_match_input (hb_would_apply_context_t *c,
+                                      unsigned int count, /* Including the first glyph (not matched) */
+                                      const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                      match_func_t match_func,
+                                      const void *match_data)
+{
+  if (count != c->len)
+    return false;
+
+  for (unsigned int i = 1; i < count; i++)
+    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
+      return false;
+
+  return true;
+}
+static inline bool match_input (hb_ot_apply_context_t *c,
+                                unsigned int count, /* Including the first glyph (not matched) */
+                                const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                match_func_t match_func,
+                                const void *match_data,
+                                unsigned int *end_offset,
+                                unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
+                                unsigned int *p_total_component_count = nullptr)
+{
+  TRACE_APPLY (nullptr);
+
+  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
+
+  hb_buffer_t *buffer = c->buffer;
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+  skippy_iter.reset (buffer->idx, count - 1);
+  skippy_iter.set_match_func (match_func, match_data, input);
+
+  /*
+   * This is perhaps the trickiest part of OpenType...  Remarks:
+   *
+   * - If all components of the ligature were marks, we call this a mark ligature.
+   *
+   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
+   *   it as a ligature glyph.
+   *
+   * - Ligatures cannot be formed across glyphs attached to different components
+   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
+   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
+   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
+   *   There are a couple of exceptions to this:
+   *
+   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
+   *     assuming that the font designer knows what they are doing (otherwise it can
+   *     break Indic stuff when a matra wants to ligate with a conjunct,
+   *
+   *   o If two marks want to ligate and they belong to different components of the
+   *     same ligature glyph, and said ligature glyph is to be ignored according to
+   *     mark-filtering rules, then allow.
+   *     https://github.com/harfbuzz/harfbuzz/issues/545
+   */
+
+  unsigned int total_component_count = 0;
+  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+
+  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+
+  enum {
+    LIGBASE_NOT_CHECKED,
+    LIGBASE_MAY_NOT_SKIP,
+    LIGBASE_MAY_SKIP
+  } ligbase = LIGBASE_NOT_CHECKED;
+
+  match_positions[0] = buffer->idx;
+  for (unsigned int i = 1; i < count; i++)
+  {
+    if (!skippy_iter.next ()) return_trace (false);
+
+    match_positions[i] = skippy_iter.idx;
+
+    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
+    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
+
+    if (first_lig_id && first_lig_comp)
+    {
+      /* If first component was attached to a previous ligature component,
+       * all subsequent components should be attached to the same ligature
+       * component, otherwise we shouldn't ligate them... */
+      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
+      {
+        /* ...unless, we are attached to a base ligature and that base
+         * ligature is ignorable. */
+        if (ligbase == LIGBASE_NOT_CHECKED)
+        {
+          bool found = false;
+          const hb_glyph_info_t *out = buffer->out_info;
+          unsigned int j = buffer->out_len;
+          while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
+          {
+            if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
+            {
+              j--;
+              found = true;
+              break;
+            }
+            j--;
+          }
+
+          if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
+            ligbase = LIGBASE_MAY_SKIP;
+          else
+            ligbase = LIGBASE_MAY_NOT_SKIP;
+        }
+
+        if (ligbase == LIGBASE_MAY_NOT_SKIP)
+          return_trace (false);
+      }
+    }
+    else
+    {
+      /* If first component was NOT attached to a previous ligature component,
+       * all subsequent components should also NOT be attached to any ligature
+       * component, unless they are attached to the first component itself! */
+      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
+        return_trace (false);
+    }
+
+    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
+  }
+
+  *end_offset = skippy_iter.idx - buffer->idx + 1;
+
+  if (p_total_component_count)
+    *p_total_component_count = total_component_count;
+
+  return_trace (true);
+}
+static inline bool ligate_input (hb_ot_apply_context_t *c,
+                                 unsigned int count, /* Including the first glyph */
+                                 const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+                                 unsigned int match_length,
+                                 hb_codepoint_t lig_glyph,
+                                 unsigned int total_component_count)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_buffer_t *buffer = c->buffer;
+
+  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
+
+  /* - If a base and one or more marks ligate, consider that as a base, NOT
+   *   ligature, such that all following marks can still attach to it.
+   *   https://github.com/harfbuzz/harfbuzz/issues/1109
+   *
+   * - If all components of the ligature were marks, we call this a mark ligature.
+   *   If it *is* a mark ligature, we don't allocate a new ligature id, and leave
+   *   the ligature to keep its old ligature id.  This will allow it to attach to
+   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
+   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA with a
+   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
+   *   later, we don't want them to lose their ligature id/component, otherwise
+   *   GPOS will fail to correctly position the mark ligature on top of the
+   *   LAM,LAM,HEH ligature.  See:
+   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
+   *
+   * - If a ligature is formed of components that some of which are also ligatures
+   *   themselves, and those ligature components had marks attached to *their*
+   *   components, we have to attach the marks to the new ligature component
+   *   positions!  Now *that*'s tricky!  And these marks may be following the
+   *   last component of the whole sequence, so we should loop forward looking
+   *   for them and update them.
+   *
+   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
+   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
+   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
+   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
+   *   the new ligature with a component value of 2.
+   *
+   *   This in fact happened to a font...  See:
+   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
+   */
+
+  bool is_base_ligature = _hb_glyph_info_is_base_glyph (&buffer->info[match_positions[0]]);
+  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->info[match_positions[0]]);
+  for (unsigned int i = 1; i < count; i++)
+    if (!_hb_glyph_info_is_mark (&buffer->info[match_positions[i]]))
+    {
+      is_base_ligature = false;
+      is_mark_ligature = false;
+      break;
+    }
+  bool is_ligature = !is_base_ligature && !is_mark_ligature;
+
+  unsigned int klass = is_ligature ? HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE : 0;
+  unsigned int lig_id = is_ligature ? _hb_allocate_lig_id (buffer) : 0;
+  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+  unsigned int components_so_far = last_num_components;
+
+  if (is_ligature)
+  {
+    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
+    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
+    {
+      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
+    }
+  }
+  c->replace_glyph_with_ligature (lig_glyph, klass);
+
+  for (unsigned int i = 1; i < count; i++)
+  {
+    while (buffer->idx < match_positions[i] && buffer->successful)
+    {
+      if (is_ligature)
+      {
+        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+        if (this_comp == 0)
+          this_comp = last_num_components;
+        unsigned int new_lig_comp = components_so_far - last_num_components +
+                                    MIN (this_comp, last_num_components);
+          _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
+      }
+      buffer->next_glyph ();
+    }
+
+    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
+    components_so_far += last_num_components;
+
+    /* Skip the base glyph */
+    buffer->idx++;
+  }
+
+  if (!is_mark_ligature && last_lig_id) {
+    /* Re-adjust components for any marks following. */
+    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
+      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
+        unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
+        if (!this_comp)
+          break;
+        unsigned int new_lig_comp = components_so_far - last_num_components +
+                                    MIN (this_comp, last_num_components);
+        _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
+      } else
+        break;
+    }
+  }
+  return_trace (true);
+}
+
+static inline bool match_backtrack (hb_ot_apply_context_t *c,
+                                    unsigned int count,
+                                    const HBUINT16 backtrack[],
+                                    match_func_t match_func,
+                                    const void *match_data,
+                                    unsigned int *match_start)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  skippy_iter.reset (c->buffer->backtrack_len (), count);
+  skippy_iter.set_match_func (match_func, match_data, backtrack);
+
+  for (unsigned int i = 0; i < count; i++)
+    if (!skippy_iter.prev ())
+      return_trace (false);
+
+  *match_start = skippy_iter.idx;
+
+  return_trace (true);
+}
+
+static inline bool match_lookahead (hb_ot_apply_context_t *c,
+                                    unsigned int count,
+                                    const HBUINT16 lookahead[],
+                                    match_func_t match_func,
+                                    const void *match_data,
+                                    unsigned int offset,
+                                    unsigned int *end_index)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
+  skippy_iter.reset (c->buffer->idx + offset - 1, count);
+  skippy_iter.set_match_func (match_func, match_data, lookahead);
+
+  for (unsigned int i = 0; i < count; i++)
+    if (!skippy_iter.next ())
+      return_trace (false);
+
+  *end_index = skippy_iter.idx + 1;
+
+  return_trace (true);
+}
+
+
+
+struct LookupRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  HBUINT16      sequenceIndex;          /* Index into current glyph
+                                         * sequence--first glyph = 0 */
+  HBUINT16      lookupListIndex;        /* Lookup to apply to that
+                                         * position--zero--based */
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+template <typename context_t>
+static inline void recurse_lookups (context_t *c,
+                                    unsigned int lookupCount,
+                                    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
+{
+  for (unsigned int i = 0; i < lookupCount; i++)
+    c->recurse (lookupRecord[i].lookupListIndex);
+}
+
+static inline bool apply_lookup (hb_ot_apply_context_t *c,
+                                 unsigned int count, /* Including the first glyph */
+                                 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
+                                 unsigned int lookupCount,
+                                 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
+                                 unsigned int match_length)
+{
+  TRACE_APPLY (nullptr);
+
+  hb_buffer_t *buffer = c->buffer;
+  int end;
+
+  /* All positions are distance from beginning of *output* buffer.
+   * Adjust. */
+  {
+    unsigned int bl = buffer->backtrack_len ();
+    end = bl + match_length;
+
+    int delta = bl - buffer->idx;
+    /* Convert positions to new indexing. */
+    for (unsigned int j = 0; j < count; j++)
+      match_positions[j] += delta;
+  }
+
+  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
+  {
+    unsigned int idx = lookupRecord[i].sequenceIndex;
+    if (idx >= count)
+      continue;
+
+    /* Don't recurse to ourself at same position.
+     * Note that this test is too naive, it doesn't catch longer loops. */
+    if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
+      continue;
+
+    if (unlikely (!buffer->move_to (match_positions[idx])))
+      break;
+
+    if (unlikely (buffer->max_ops <= 0))
+      break;
+
+    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
+    if (!c->recurse (lookupRecord[i].lookupListIndex))
+      continue;
+
+    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
+    int delta = new_len - orig_len;
+
+    if (!delta)
+      continue;
+
+    /* Recursed lookup changed buffer len.  Adjust.
+     *
+     * TODO:
+     *
+     * Right now, if buffer length increased by n, we assume n new glyphs
+     * were added right after the current position, and if buffer length
+     * was decreased by n, we assume n match positions after the current
+     * one where removed.  The former (buffer length increased) case is
+     * fine, but the decrease case can be improved in at least two ways,
+     * both of which are significant:
+     *
+     *   - If recursed-to lookup is MultipleSubst and buffer length
+     *     decreased, then it's current match position that was deleted,
+     *     NOT the one after it.
+     *
+     *   - If buffer length was decreased by n, it does not necessarily
+     *     mean that n match positions where removed, as there might
+     *     have been marks and default-ignorables in the sequence.  We
+     *     should instead drop match positions between current-position
+     *     and current-position + n instead.
+     *
+     * It should be possible to construct tests for both of these cases.
+     */
+
+    end += delta;
+    if (end <= int (match_positions[idx]))
+    {
+      /* End might end up being smaller than match_positions[idx] if the recursed
+       * lookup ended up removing many items, more than we have had matched.
+       * Just never rewind end back and get out of here.
+       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
+      end = match_positions[idx];
+      /* There can't be any further changes. */
+      break;
+    }
+
+    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
+
+    if (delta > 0)
+    {
+      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
+        break;
+    }
+    else
+    {
+      /* NOTE: delta is negative. */
+      delta = MAX (delta, (int) next - (int) count);
+      next -= delta;
+    }
+
+    /* Shift! */
+    memmove (match_positions + next + delta, match_positions + next,
+             (count - next) * sizeof (match_positions[0]));
+    next += delta;
+    count += delta;
+
+    /* Fill in new entries. */
+    for (unsigned int j = idx + 1; j < next; j++)
+      match_positions[j] = match_positions[j - 1] + 1;
+
+    /* And fixup the rest. */
+    for (; next < count; next++)
+      match_positions[next] += delta;
+  }
+
+  buffer->move_to (end);
+
+  return_trace (true);
+}
+
+
+
+/* Contextual lookups */
+
+struct ContextClosureLookupContext
+{
+  ContextClosureFuncs funcs;
+  const void *intersects_data;
+};
+
+struct ContextCollectGlyphsLookupContext
+{
+  ContextCollectGlyphsFuncs funcs;
+  const void *collect_data;
+};
+
+struct ContextApplyLookupContext
+{
+  ContextApplyFuncs funcs;
+  const void *match_data;
+};
+
+static inline bool context_intersects (const hb_set_t *glyphs,
+                                       unsigned int inputCount, /* Including the first glyph (not matched) */
+                                       const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                       ContextClosureLookupContext &lookup_context)
+{
+  return intersects_array (glyphs,
+                           inputCount ? inputCount - 1 : 0, input,
+                           lookup_context.funcs.intersects, lookup_context.intersects_data);
+}
+
+static inline void context_closure_lookup (hb_closure_context_t *c,
+                                           unsigned int inputCount, /* Including the first glyph (not matched) */
+                                           const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                           unsigned int lookupCount,
+                                           const LookupRecord lookupRecord[],
+                                           ContextClosureLookupContext &lookup_context)
+{
+  if (context_intersects (c->glyphs,
+                          inputCount, input,
+                          lookup_context))
+    recurse_lookups (c,
+                     lookupCount, lookupRecord);
+}
+
+static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
+                                                  unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                  const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                  unsigned int lookupCount,
+                                                  const LookupRecord lookupRecord[],
+                                                  ContextCollectGlyphsLookupContext &lookup_context)
+{
+  collect_array (c, c->input,
+                 inputCount ? inputCount - 1 : 0, input,
+                 lookup_context.funcs.collect, lookup_context.collect_data);
+  recurse_lookups (c,
+                   lookupCount, lookupRecord);
+}
+
+static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
+                                               unsigned int inputCount, /* Including the first glyph (not matched) */
+                                               const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                               unsigned int lookupCount HB_UNUSED,
+                                               const LookupRecord lookupRecord[] HB_UNUSED,
+                                               ContextApplyLookupContext &lookup_context)
+{
+  return would_match_input (c,
+                            inputCount, input,
+                            lookup_context.funcs.match, lookup_context.match_data);
+}
+static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
+                                         unsigned int inputCount, /* Including the first glyph (not matched) */
+                                         const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                         unsigned int lookupCount,
+                                         const LookupRecord lookupRecord[],
+                                         ContextApplyLookupContext &lookup_context)
+{
+  unsigned int match_length = 0;
+  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+  return match_input (c,
+                      inputCount, input,
+                      lookup_context.funcs.match, lookup_context.match_data,
+                      &match_length, match_positions)
+      && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
+          apply_lookup (c,
+                       inputCount, match_positions,
+                       lookupCount, lookupRecord,
+                       match_length));
+}
+
+struct Rule
+{
+  bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
+  {
+    return context_intersects (glyphs,
+                               inputCount, inputZ.arrayZ,
+                               lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
+  {
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                       (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+    context_closure_lookup (c,
+                            inputCount, inputZ.arrayZ,
+                            lookupCount, lookupRecord.arrayZ,
+                            lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                       ContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    context_collect_glyphs_lookup (c,
+                                   inputCount, inputZ.arrayZ,
+                                   lookupCount, lookupRecord.arrayZ,
+                                   lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                    ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    return_trace (context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
+  }
+
+  bool apply (hb_ot_apply_context_t *c,
+              ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
+                                                       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+    return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
+  }
+
+  public:
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (inputCount.sanitize (c) &&
+                  lookupCount.sanitize (c) &&
+                  c->check_range (inputZ.arrayZ,
+                                  inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
+                                  LookupRecord::static_size * lookupCount));
+  }
+
+  protected:
+  HBUINT16      inputCount;             /* Total number of glyphs in input
+                                         * glyph sequence--includes the first
+                                         * glyph */
+  HBUINT16      lookupCount;            /* Number of LookupRecords */
+  UnsizedArrayOf<HBUINT16>
+                inputZ;                 /* Array of match inputs--start with
+                                         * second glyph */
+/*UnsizedArrayOf<LookupRecord>
+                lookupRecordX;*/        /* Array of LookupRecords--in
+                                         * design order */
+  public:
+  DEFINE_SIZE_ARRAY (4, inputZ);
+};
+
+struct RuleSet
+{
+  bool intersects (const hb_set_t *glyphs,
+                   ContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).intersects (glyphs, lookup_context))
+        return true;
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c,
+                ContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).closure (c, lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                       ContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                    ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+    {
+      if ((this+rule[i]).would_apply (c, lookup_context))
+        return_trace (true);
+    }
+    return_trace (false);
+  }
+
+  bool apply (hb_ot_apply_context_t *c,
+              ContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+    {
+      if ((this+rule[i]).apply (c, lookup_context))
+        return_trace (true);
+    }
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rule.sanitize (c, this));
+  }
+
+  protected:
+  OffsetArrayOf<Rule>
+                rule;                   /* Array of Rule tables
+                                         * ordered by preference */
+  public:
+  DEFINE_SIZE_ARRAY (2, rule);
+};
+
+
+struct ContextFormat1
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+          (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
+        return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (c->glyphs->has (iter.get_glyph ()))
+        (this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
+    }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_glyph},
+      nullptr
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      nullptr
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED))
+      return_trace (false);
+
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      nullptr
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 1 */
+  OffsetTo<Coverage>
+                coverage;               /* Offset to Coverage table--from
+                                         * beginning of table */
+  OffsetArrayOf<RuleSet>
+                ruleSet;                /* Array of RuleSet tables
+                                         * ordered by Coverage Index */
+  public:
+  DEFINE_SIZE_ARRAY (6, ruleSet);
+};
+
+
+struct ContextFormat2
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const ClassDef &class_def = this+classDef;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (class_def.intersects_class (glyphs, i) &&
+          (this+ruleSet[i]).intersects (glyphs, lookup_context))
+        return true;
+
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverage).intersects (c->glyphs))
+      return;
+
+    const ClassDef &class_def = this+classDef;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (class_def.intersects_class (c->glyphs, i)) {
+        const RuleSet &rule_set = this+ruleSet[i];
+        rule_set.closure (c, lookup_context);
+      }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    const ClassDef &class_def = this+classDef;
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_class},
+      &class_def
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ClassDef &class_def = this+classDef;
+    unsigned int index = class_def.get_class (c->glyphs[0]);
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_class},
+      &class_def
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ClassDef &class_def = this+classDef;
+    index = class_def.get_class (c->buffer->cur().codepoint);
+    const RuleSet &rule_set = this+ruleSet[index];
+    struct ContextApplyLookupContext lookup_context = {
+      {match_class},
+      &class_def
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 2 */
+  OffsetTo<Coverage>
+                coverage;               /* Offset to Coverage table--from
+                                         * beginning of table */
+  OffsetTo<ClassDef>
+                classDef;               /* Offset to glyph ClassDef table--from
+                                         * beginning of table */
+  OffsetArrayOf<RuleSet>
+                ruleSet;                /* Array of RuleSet tables
+                                         * ordered by class */
+  public:
+  DEFINE_SIZE_ARRAY (8, ruleSet);
+};
+
+
+struct ContextFormat3
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverageZ[0]).intersects (glyphs))
+      return false;
+
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      this
+    };
+    return context_intersects (glyphs,
+                               glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                               lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverageZ[0]).intersects (c->glyphs))
+      return;
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      this
+    };
+    context_closure_lookup (c,
+                            glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                            lookupCount, lookupRecord,
+                            lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverageZ[0]).add_coverage (c->input);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextCollectGlyphsLookupContext lookup_context = {
+      {collect_coverage},
+      this
+    };
+
+    context_collect_glyphs_lookup (c,
+                                   glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
+                                   lookupCount, lookupRecord,
+                                   lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      this
+    };
+    return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverageZ[0]; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    struct ContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      this
+    };
+    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!c->check_struct (this)) return_trace (false);
+    unsigned int count = glyphCount;
+    if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
+    if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
+    for (unsigned int i = 0; i < count; i++)
+      if (!coverageZ[i].sanitize (c, this)) return_trace (false);
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    return_trace (c->check_array (lookupRecord, lookupCount));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 3 */
+  HBUINT16      glyphCount;             /* Number of glyphs in the input glyph
+                                         * sequence */
+  HBUINT16      lookupCount;            /* Number of LookupRecords */
+  UnsizedArrayOf<OffsetTo<Coverage> >
+                coverageZ;              /* Array of offsets to Coverage
+                                         * table in glyph sequence order */
+/*UnsizedArrayOf<LookupRecord>
+                lookupRecordX;*/        /* Array of LookupRecords--in
+                                         * design order */
+  public:
+  DEFINE_SIZE_ARRAY (6, coverageZ);
+};
+
+struct Context
+{
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    case 3: return_trace (c->dispatch (u.format3));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  ContextFormat1        format1;
+  ContextFormat2        format2;
+  ContextFormat3        format3;
+  } u;
+};
+
+
+/* Chaining Contextual lookups */
+
+struct ChainContextClosureLookupContext
+{
+  ContextClosureFuncs funcs;
+  const void *intersects_data[3];
+};
+
+struct ChainContextCollectGlyphsLookupContext
+{
+  ContextCollectGlyphsFuncs funcs;
+  const void *collect_data[3];
+};
+
+struct ChainContextApplyLookupContext
+{
+  ContextApplyFuncs funcs;
+  const void *match_data[3];
+};
+
+static inline bool chain_context_intersects (const hb_set_t *glyphs,
+                                             unsigned int backtrackCount,
+                                             const HBUINT16 backtrack[],
+                                             unsigned int inputCount, /* Including the first glyph (not matched) */
+                                             const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                             unsigned int lookaheadCount,
+                                             const HBUINT16 lookahead[],
+                                             ChainContextClosureLookupContext &lookup_context)
+{
+  return intersects_array (glyphs,
+                           backtrackCount, backtrack,
+                           lookup_context.funcs.intersects, lookup_context.intersects_data[0])
+      && intersects_array (glyphs,
+                           inputCount ? inputCount - 1 : 0, input,
+                           lookup_context.funcs.intersects, lookup_context.intersects_data[1])
+      && intersects_array (glyphs,
+                          lookaheadCount, lookahead,
+                          lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
+}
+
+static inline void chain_context_closure_lookup (hb_closure_context_t *c,
+                                                 unsigned int backtrackCount,
+                                                 const HBUINT16 backtrack[],
+                                                 unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                 const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                 unsigned int lookaheadCount,
+                                                 const HBUINT16 lookahead[],
+                                                 unsigned int lookupCount,
+                                                 const LookupRecord lookupRecord[],
+                                                 ChainContextClosureLookupContext &lookup_context)
+{
+  if (chain_context_intersects (c->glyphs,
+                                backtrackCount, backtrack,
+                                inputCount, input,
+                                lookaheadCount, lookahead,
+                                lookup_context))
+    recurse_lookups (c,
+                     lookupCount, lookupRecord);
+}
+
+static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
+                                                        unsigned int backtrackCount,
+                                                        const HBUINT16 backtrack[],
+                                                        unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                        const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                        unsigned int lookaheadCount,
+                                                        const HBUINT16 lookahead[],
+                                                        unsigned int lookupCount,
+                                                        const LookupRecord lookupRecord[],
+                                                        ChainContextCollectGlyphsLookupContext &lookup_context)
+{
+  collect_array (c, c->before,
+                 backtrackCount, backtrack,
+                 lookup_context.funcs.collect, lookup_context.collect_data[0]);
+  collect_array (c, c->input,
+                 inputCount ? inputCount - 1 : 0, input,
+                 lookup_context.funcs.collect, lookup_context.collect_data[1]);
+  collect_array (c, c->after,
+                 lookaheadCount, lookahead,
+                 lookup_context.funcs.collect, lookup_context.collect_data[2]);
+  recurse_lookups (c,
+                   lookupCount, lookupRecord);
+}
+
+static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
+                                                     unsigned int backtrackCount,
+                                                     const HBUINT16 backtrack[] HB_UNUSED,
+                                                     unsigned int inputCount, /* Including the first glyph (not matched) */
+                                                     const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                                     unsigned int lookaheadCount,
+                                                     const HBUINT16 lookahead[] HB_UNUSED,
+                                                     unsigned int lookupCount HB_UNUSED,
+                                                     const LookupRecord lookupRecord[] HB_UNUSED,
+                                                     ChainContextApplyLookupContext &lookup_context)
+{
+  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
+      && would_match_input (c,
+                            inputCount, input,
+                            lookup_context.funcs.match, lookup_context.match_data[1]);
+}
+
+static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
+                                               unsigned int backtrackCount,
+                                               const HBUINT16 backtrack[],
+                                               unsigned int inputCount, /* Including the first glyph (not matched) */
+                                               const HBUINT16 input[], /* Array of input values--start with second glyph */
+                                               unsigned int lookaheadCount,
+                                               const HBUINT16 lookahead[],
+                                               unsigned int lookupCount,
+                                               const LookupRecord lookupRecord[],
+                                               ChainContextApplyLookupContext &lookup_context)
+{
+  unsigned int start_index = 0, match_length = 0, end_index = 0;
+  unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+  return match_input (c,
+                      inputCount, input,
+                      lookup_context.funcs.match, lookup_context.match_data[1],
+                      &match_length, match_positions)
+      && match_backtrack (c,
+                          backtrackCount, backtrack,
+                          lookup_context.funcs.match, lookup_context.match_data[0],
+                          &start_index)
+      && match_lookahead (c,
+                          lookaheadCount, lookahead,
+                          lookup_context.funcs.match, lookup_context.match_data[2],
+                          match_length, &end_index)
+      && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
+          apply_lookup (c,
+                        inputCount, match_positions,
+                        lookupCount, lookupRecord,
+                        match_length));
+}
+
+struct ChainRule
+{
+  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    return chain_context_intersects (glyphs,
+                                     backtrack.len, backtrack.arrayZ,
+                                     input.lenP1, input.arrayZ,
+                                     lookahead.len, lookahead.arrayZ,
+                                     lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c,
+                ChainContextClosureLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    chain_context_closure_lookup (c,
+                                  backtrack.len, backtrack.arrayZ,
+                                  input.lenP1, input.arrayZ,
+                                  lookahead.len, lookahead.arrayZ,
+                                  lookup.len, lookup.arrayZ,
+                                  lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c,
+                       ChainContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    chain_context_collect_glyphs_lookup (c,
+                                         backtrack.len, backtrack.arrayZ,
+                                         input.lenP1, input.arrayZ,
+                                         lookahead.len, lookahead.arrayZ,
+                                         lookup.len, lookup.arrayZ,
+                                         lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c,
+                    ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (chain_context_would_apply_lookup (c,
+                                                    backtrack.len, backtrack.arrayZ,
+                                                    input.lenP1, input.arrayZ,
+                                                    lookahead.len, lookahead.arrayZ, lookup.len,
+                                                    lookup.arrayZ, lookup_context));
+  }
+
+  bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (chain_context_apply_lookup (c,
+                                              backtrack.len, backtrack.arrayZ,
+                                              input.lenP1, input.arrayZ,
+                                              lookahead.len, lookahead.arrayZ, lookup.len,
+                                              lookup.arrayZ, lookup_context));
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!backtrack.sanitize (c)) return_trace (false);
+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
+    if (!input.sanitize (c)) return_trace (false);
+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
+    if (!lookahead.sanitize (c)) return_trace (false);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (lookup.sanitize (c));
+  }
+
+  protected:
+  ArrayOf<HBUINT16>
+                backtrack;              /* Array of backtracking values
+                                         * (to be matched before the input
+                                         * sequence) */
+  HeadlessArrayOf<HBUINT16>
+                inputX;                 /* Array of input values (start with
+                                         * second glyph) */
+  ArrayOf<HBUINT16>
+                lookaheadX;             /* Array of lookahead values's (to be
+                                         * matched after the input sequence) */
+  ArrayOf<LookupRecord>
+                lookupX;                /* Array of LookupRecords--in
+                                         * design order) */
+  public:
+  DEFINE_SIZE_MIN (8);
+};
+
+struct ChainRuleSet
+{
+  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).intersects (glyphs, lookup_context))
+        return true;
+    return false;
+  }
+  void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).closure (c, lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
+  {
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      (this+rule[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_WOULD_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).would_apply (c, lookup_context))
+        return_trace (true);
+
+    return_trace (false);
+  }
+
+  bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
+  {
+    TRACE_APPLY (this);
+    unsigned int num_rules = rule.len;
+    for (unsigned int i = 0; i < num_rules; i++)
+      if ((this+rule[i]).apply (c, lookup_context))
+        return_trace (true);
+
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (rule.sanitize (c, this));
+  }
+
+  protected:
+  OffsetArrayOf<ChainRule>
+                rule;                   /* Array of ChainRule tables
+                                         * ordered by preference */
+  public:
+  DEFINE_SIZE_ARRAY (2, rule);
+};
+
+struct ChainContextFormat1
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (glyphs->has (iter.get_glyph ()) &&
+          (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
+        return true;
+    }
+    return false;
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
+    {
+      if (unlikely (iter.get_coverage () >= count))
+        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
+      if (c->glyphs->has (iter.get_glyph ()))
+        (this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
+    }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_glyph},
+      {nullptr, nullptr, nullptr}
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 1 */
+  OffsetTo<Coverage>
+                coverage;               /* Offset to Coverage table--from
+                                         * beginning of table */
+  OffsetArrayOf<ChainRuleSet>
+                ruleSet;                /* Array of ChainRuleSet tables
+                                         * ordered by Coverage Index */
+  public:
+  DEFINE_SIZE_ARRAY (6, ruleSet);
+};
+
+struct ChainContextFormat2
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    if (!(this+coverage).intersects (glyphs))
+      return false;
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (input_class_def.intersects_class (glyphs, i) &&
+          (this+ruleSet[i]).intersects (glyphs, lookup_context))
+        return true;
+
+    return false;
+  }
+  void closure (hb_closure_context_t *c) const
+  {
+    if (!(this+coverage).intersects (c->glyphs))
+      return;
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      if (input_class_def.intersects_class (c->glyphs, i)) {
+        const ChainRuleSet &rule_set = this+ruleSet[i];
+        rule_set.closure (c, lookup_context);
+      }
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    (this+coverage).add_coverage (c->input);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+
+    unsigned int count = ruleSet.len;
+    for (unsigned int i = 0; i < count; i++)
+      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    unsigned int index = input_class_def.get_class (c->glyphs[0]);
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+    return_trace (rule_set.would_apply (c, lookup_context));
+  }
+
+  const Coverage &get_coverage () const { return this+coverage; }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const ClassDef &backtrack_class_def = this+backtrackClassDef;
+    const ClassDef &input_class_def = this+inputClassDef;
+    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
+
+    index = input_class_def.get_class (c->buffer->cur().codepoint);
+    const ChainRuleSet &rule_set = this+ruleSet[index];
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_class},
+      {&backtrack_class_def,
+       &input_class_def,
+       &lookahead_class_def}
+    };
+    return_trace (rule_set.apply (c, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (coverage.sanitize (c, this) &&
+                  backtrackClassDef.sanitize (c, this) &&
+                  inputClassDef.sanitize (c, this) &&
+                  lookaheadClassDef.sanitize (c, this) &&
+                  ruleSet.sanitize (c, this));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 2 */
+  OffsetTo<Coverage>
+                coverage;               /* Offset to Coverage table--from
+                                         * beginning of table */
+  OffsetTo<ClassDef>
+                backtrackClassDef;      /* Offset to glyph ClassDef table
+                                         * containing backtrack sequence
+                                         * data--from beginning of table */
+  OffsetTo<ClassDef>
+                inputClassDef;          /* Offset to glyph ClassDef
+                                         * table containing input sequence
+                                         * data--from beginning of table */
+  OffsetTo<ClassDef>
+                lookaheadClassDef;      /* Offset to glyph ClassDef table
+                                         * containing lookahead sequence
+                                         * data--from beginning of table */
+  OffsetArrayOf<ChainRuleSet>
+                ruleSet;                /* Array of ChainRuleSet tables
+                                         * ordered by class */
+  public:
+  DEFINE_SIZE_ARRAY (12, ruleSet);
+};
+
+struct ChainContextFormat3
+{
+  bool intersects (const hb_set_t *glyphs) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    if (!(this+input[0]).intersects (glyphs))
+      return false;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      {this, this, this}
+    };
+    return chain_context_intersects (glyphs,
+                                     backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                     input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                     lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                     lookup_context);
+  }
+
+  void closure (hb_closure_context_t *c) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    if (!(this+input[0]).intersects (c->glyphs))
+      return;
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextClosureLookupContext lookup_context = {
+      {intersects_coverage},
+      {this, this, this}
+    };
+    chain_context_closure_lookup (c,
+                                  backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                  input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                  lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                  lookup.len, lookup.arrayZ,
+                                  lookup_context);
+  }
+
+  void collect_glyphs (hb_collect_glyphs_context_t *c) const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    (this+input[0]).add_coverage (c->input);
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextCollectGlyphsLookupContext lookup_context = {
+      {collect_coverage},
+      {this, this, this}
+    };
+    chain_context_collect_glyphs_lookup (c,
+                                         backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                         input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                         lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                         lookup.len, lookup.arrayZ,
+                                         lookup_context);
+  }
+
+  bool would_apply (hb_would_apply_context_t *c) const
+  {
+    TRACE_WOULD_APPLY (this);
+
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      {this, this, this}
+    };
+    return_trace (chain_context_would_apply_lookup (c,
+                                                    backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                                    input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                                    lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                                    lookup.len, lookup.arrayZ, lookup_context));
+  }
+
+  const Coverage &get_coverage () const
+  {
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    return this+input[0];
+  }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+
+    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
+    if (likely (index == NOT_COVERED)) return_trace (false);
+
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    struct ChainContextApplyLookupContext lookup_context = {
+      {match_coverage},
+      {this, this, this}
+    };
+    return_trace (chain_context_apply_lookup (c,
+                                              backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
+                                              input.len, (const HBUINT16 *) input.arrayZ + 1,
+                                              lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
+                                              lookup.len, lookup.arrayZ, lookup_context));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    // TODO(subset)
+    return_trace (false);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!backtrack.sanitize (c, this)) return_trace (false);
+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
+    if (!input.sanitize (c, this)) return_trace (false);
+    if (!input.len) return_trace (false); /* To be consistent with Context. */
+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
+    if (!lookahead.sanitize (c, this)) return_trace (false);
+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
+    return_trace (lookup.sanitize (c));
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier--format = 3 */
+  OffsetArrayOf<Coverage>
+                backtrack;              /* Array of coverage tables
+                                         * in backtracking sequence, in  glyph
+                                         * sequence order */
+  OffsetArrayOf<Coverage>
+                inputX          ;       /* Array of coverage
+                                         * tables in input sequence, in glyph
+                                         * sequence order */
+  OffsetArrayOf<Coverage>
+                lookaheadX;             /* Array of coverage tables
+                                         * in lookahead sequence, in glyph
+                                         * sequence order */
+  ArrayOf<LookupRecord>
+                lookupX;                /* Array of LookupRecords--in
+                                         * design order) */
+  public:
+  DEFINE_SIZE_MIN (10);
+};
+
+struct ChainContext
+{
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (c->dispatch (u.format1));
+    case 2: return_trace (c->dispatch (u.format2));
+    case 3: return_trace (c->dispatch (u.format3));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format; /* Format identifier */
+  ChainContextFormat1   format1;
+  ChainContextFormat2   format2;
+  ChainContextFormat3   format3;
+  } u;
+};
+
+
+template <typename T>
+struct ExtensionFormat1
+{
+  unsigned int get_type () const { return extensionLookupType; }
+
+  template <typename X>
+  const X& get_subtable () const
+  {
+    unsigned int offset = extensionOffset;
+    if (unlikely (!offset)) return Null(typename T::SubTable);
+    return StructAtOffset<typename T::SubTable> (this, offset);
+  }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, format);
+    if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
+    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type ()));
+  }
+
+  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  extensionOffset != 0 &&
+                  extensionLookupType != T::SubTable::Extension);
+  }
+
+  protected:
+  HBUINT16      format;                 /* Format identifier. Set to 1. */
+  HBUINT16      extensionLookupType;    /* Lookup type of subtable referenced
+                                         * by ExtensionOffset (i.e. the
+                                         * extension subtable). */
+  HBUINT32      extensionOffset;        /* Offset to the extension subtable,
+                                         * of lookup type subtable. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+template <typename T>
+struct Extension
+{
+  unsigned int get_type () const
+  {
+    switch (u.format) {
+    case 1: return u.format1.get_type ();
+    default:return 0;
+    }
+  }
+  template <typename X>
+  const X& get_subtable () const
+  {
+    switch (u.format) {
+    case 1: return u.format1.template get_subtable<typename T::SubTable> ();
+    default:return Null(typename T::SubTable);
+    }
+  }
+
+  template <typename context_t>
+  typename context_t::return_t dispatch (context_t *c) const
+  {
+    TRACE_DISPATCH (this, u.format);
+    if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+    switch (u.format) {
+    case 1: return_trace (u.format1.dispatch (c));
+    default:return_trace (c->default_return_value ());
+    }
+  }
+
+  protected:
+  union {
+  HBUINT16              format;         /* Format identifier */
+  ExtensionFormat1<T>   format1;
+  } u;
+};
+
+
+/*
+ * GSUB/GPOS Common
+ */
+
+struct hb_ot_layout_lookup_accelerator_t
+{
+  template <typename TLookup>
+  void init (const TLookup &lookup)
+  {
+    digest.init ();
+    lookup.add_coverage (&digest);
+
+    subtables.init ();
+    OT::hb_get_subtables_context_t c_get_subtables (subtables);
+    lookup.dispatch (&c_get_subtables);
+  }
+  void fini () { subtables.fini (); }
+
+  bool may_have (hb_codepoint_t g) const
+  { return digest.may_have (g); }
+
+  bool apply (hb_ot_apply_context_t *c) const
+  {
+    for (unsigned int i = 0; i < subtables.length; i++)
+      if (subtables[i].apply (c))
+        return true;
+    return false;
+  }
+
+  private:
+  hb_set_digest_t digest;
+  hb_get_subtables_context_t::array_t subtables;
+};
+
+struct GSUBGPOS
+{
+  bool has_data () const { return version.to_int (); }
+  unsigned int get_script_count () const
+  { return (this+scriptList).len; }
+  const Tag& get_script_tag (unsigned int i) const
+  { return (this+scriptList).get_tag (i); }
+  unsigned int get_script_tags (unsigned int start_offset,
+                                unsigned int *script_count /* IN/OUT */,
+                                hb_tag_t     *script_tags /* OUT */) const
+  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
+  const Script& get_script (unsigned int i) const
+  { return (this+scriptList)[i]; }
+  bool find_script_index (hb_tag_t tag, unsigned int *index) const
+  { return (this+scriptList).find_index (tag, index); }
+
+  unsigned int get_feature_count () const
+  { return (this+featureList).len; }
+  hb_tag_t get_feature_tag (unsigned int i) const
+  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
+  unsigned int get_feature_tags (unsigned int start_offset,
+                                 unsigned int *feature_count /* IN/OUT */,
+                                 hb_tag_t     *feature_tags /* OUT */) const
+  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
+  const Feature& get_feature (unsigned int i) const
+  { return (this+featureList)[i]; }
+  bool find_feature_index (hb_tag_t tag, unsigned int *index) const
+  { return (this+featureList).find_index (tag, index); }
+
+  unsigned int get_lookup_count () const
+  { return (this+lookupList).len; }
+  const Lookup& get_lookup (unsigned int i) const
+  { return (this+lookupList)[i]; }
+
+  bool find_variations_index (const int *coords, unsigned int num_coords,
+                              unsigned int *index) const
+  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
+           .find_index (coords, num_coords, index); }
+  const Feature& get_feature_variation (unsigned int feature_index,
+                                        unsigned int variations_index) const
+  {
+    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
+        version.to_int () >= 0x00010001u)
+    {
+      const Feature *feature = (this+featureVars).find_substitute (variations_index,
+                                                                   feature_index);
+      if (feature)
+        return *feature;
+    }
+    return get_feature (feature_index);
+  }
+
+  template <typename TLookup>
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    struct GSUBGPOS *out = c->serializer->embed (*this);
+    if (unlikely (!out)) return_trace (false);
+
+    out->scriptList.serialize_subset (c, this+scriptList, out);
+    out->featureList.serialize_subset (c, this+featureList, out);
+
+    typedef OffsetListOf<TLookup> TLookupList;
+    /* TODO Use intersects() to count how many subtables survive? */
+    CastR<OffsetTo<TLookupList> > (out->lookupList)
+      .serialize_subset (c,
+                         this+CastR<const OffsetTo<TLookupList> > (lookupList),
+                         out);
+
+    if (version.to_int () >= 0x00010001u)
+     out->featureVars.serialize_subset (c, this+featureVars, out);
+
+    return_trace (true);
+  }
+
+  unsigned int get_size () const
+  {
+    return min_size +
+           (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
+  }
+
+  template <typename TLookup>
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    typedef OffsetListOf<TLookup> TLookupList;
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  scriptList.sanitize (c, this) &&
+                  featureList.sanitize (c, this) &&
+                  CastR<OffsetTo<TLookupList> > (lookupList).sanitize (c, this) &&
+                  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
+  }
+
+  template <typename T>
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<T> (face);
+      if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
+      {
+        hb_blob_destroy (this->table.get_blob ());
+        this->table = hb_blob_get_empty ();
+      }
+
+      this->lookup_count = table->get_lookup_count ();
+
+      this->accels = (hb_ot_layout_lookup_accelerator_t *) calloc (this->lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
+      if (unlikely (!this->accels))
+        this->lookup_count = 0;
+
+      for (unsigned int i = 0; i < this->lookup_count; i++)
+        this->accels[i].init (table->get_lookup (i));
+    }
+
+    void fini ()
+    {
+      for (unsigned int i = 0; i < this->lookup_count; i++)
+        this->accels[i].fini ();
+      free (this->accels);
+      this->table.destroy ();
+    }
+
+    hb_blob_ptr_t<T> table;
+    unsigned int lookup_count;
+    hb_ot_layout_lookup_accelerator_t *accels;
+  };
+
+  protected:
+  FixedVersion<>version;        /* Version of the GSUB/GPOS table--initially set
+                                 * to 0x00010000u */
+  OffsetTo<ScriptList>
+                scriptList;     /* ScriptList table */
+  OffsetTo<FeatureList>
+                featureList;    /* FeatureList table */
+  OffsetTo<LookupList>
+                lookupList;     /* LookupList table */
+  LOffsetTo<FeatureVariations>
+                featureVars;    /* Offset to Feature Variations
+                                   table--from beginning of table
+                                 * (may be NULL).  Introduced
+                                 * in version 0x00010001. */
+  public:
+  DEFINE_SIZE_MIN (10);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_LAYOUT_GSUBGPOS_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-jstf-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-jstf-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,7 @@
 #ifndef HB_OT_LAYOUT_JSTF_TABLE_HH
 #define HB_OT_LAYOUT_JSTF_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-layout-gpos-table.hh"
 
 
@@ -54,7 +54,7 @@
 
 struct JstfPriority
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
@@ -123,8 +123,8 @@
 
 struct JstfLangSys : OffsetListOf<JstfPriority>
 {
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<JstfLangSys>::sanitize_closure_t * = nullptr) const
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t * = nullptr) const
   {
     TRACE_SANITIZE (this);
     return_trace (OffsetListOf<JstfPriority>::sanitize (c));
@@ -145,27 +145,27 @@
 
 struct JstfScript
 {
-  inline unsigned int get_lang_sys_count (void) const
+  unsigned int get_lang_sys_count () const
   { return langSys.len; }
-  inline const Tag& get_lang_sys_tag (unsigned int i) const
+  const Tag& get_lang_sys_tag (unsigned int i) const
   { return langSys.get_tag (i); }
-  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
-                                         unsigned int *lang_sys_count /* IN/OUT */,
-                                         hb_tag_t     *lang_sys_tags /* OUT */) const
+  unsigned int get_lang_sys_tags (unsigned int start_offset,
+                                  unsigned int *lang_sys_count /* IN/OUT */,
+                                  hb_tag_t     *lang_sys_tags /* OUT */) const
   { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
-  inline const JstfLangSys& get_lang_sys (unsigned int i) const
+  const JstfLangSys& get_lang_sys (unsigned int i) const
   {
     if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
     return this+langSys[i].offset;
   }
-  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
   { return langSys.find_index (tag, index); }
 
-  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
-  inline const JstfLangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
+  bool has_default_lang_sys () const               { return defaultLangSys != 0; }
+  const JstfLangSys& get_default_lang_sys () const { return this+defaultLangSys; }
 
-  inline bool sanitize (hb_sanitize_context_t *c,
-                        const Record<JstfScript>::sanitize_closure_t * = nullptr) const
+  bool sanitize (hb_sanitize_context_t *c,
+                 const Record_sanitize_closure_t * = nullptr) const
   {
     TRACE_SANITIZE (this);
     return_trace (extenderGlyphs.sanitize (c, this) &&
@@ -195,22 +195,22 @@
 
 struct JSTF
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_JSTF;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_JSTF;
 
-  inline unsigned int get_script_count (void) const
+  unsigned int get_script_count () const
   { return scriptList.len; }
-  inline const Tag& get_script_tag (unsigned int i) const
+  const Tag& get_script_tag (unsigned int i) const
   { return scriptList.get_tag (i); }
-  inline unsigned int get_script_tags (unsigned int start_offset,
-                                       unsigned int *script_count /* IN/OUT */,
-                                       hb_tag_t     *script_tags /* OUT */) const
+  unsigned int get_script_tags (unsigned int start_offset,
+                                unsigned int *script_count /* IN/OUT */,
+                                hb_tag_t     *script_tags /* OUT */) const
   { return scriptList.get_tags (start_offset, script_count, script_tags); }
-  inline const JstfScript& get_script (unsigned int i) const
+  const JstfScript& get_script (unsigned int i) const
   { return this+scriptList[i].offset; }
-  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
+  bool find_script_index (hb_tag_t tag, unsigned int *index) const
   { return scriptList.find_index (tag, index); }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,677 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_LAYOUT_PRIVATE_HH
-#define HB_OT_LAYOUT_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-set-digest-private.hh"
-#include "hb-open-type-private.hh"
-
-
-/* Private API corresponding to hb-ot-layout.h: */
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_table_find_feature (hb_face_t    *face,
-                                 hb_tag_t      table_tag,
-                                 hb_tag_t      feature_tag,
-                                 unsigned int *feature_index);
-
-
-/*
- * GDEF
- */
-
-enum hb_ot_layout_glyph_props_flags_t
-{
-  /* The following three match LookupFlags::Ignore* numbers. */
-  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH   = 0x02u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE     = 0x04u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MARK         = 0x08u,
-
-  /* The following are used internally; not derived from GDEF. */
-  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED  = 0x10u,
-  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED      = 0x20u,
-  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED   = 0x40u,
-
-  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
-                                          HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-                                          HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
-};
-HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
-
-
-/*
- * GSUB/GPOS
- */
-
-HB_INTERNAL hb_bool_t
-hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
-                                           unsigned int          lookup_index,
-                                           const hb_codepoint_t *glyphs,
-                                           unsigned int          glyphs_length,
-                                           hb_bool_t             zero_context);
-
-
-/* Should be called before all the substitute_lookup's are done. */
-HB_INTERNAL void
-hb_ot_layout_substitute_start (hb_font_t    *font,
-                               hb_buffer_t  *buffer);
-
-
-struct hb_ot_layout_lookup_accelerator_t;
-
-namespace OT {
-  struct hb_ot_apply_context_t;
-  struct SubstLookup;
-}
-
-HB_INTERNAL void
-hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
-                                const OT::SubstLookup &lookup,
-                                const hb_ot_layout_lookup_accelerator_t &accel);
-
-
-/* Should be called before all the position_lookup's are done. */
-HB_INTERNAL void
-hb_ot_layout_position_start (hb_font_t    *font,
-                             hb_buffer_t  *buffer);
-
-/* Should be called after all the position_lookup's are done, to fini advances. */
-HB_INTERNAL void
-hb_ot_layout_position_finish_advances (hb_font_t    *font,
-                                       hb_buffer_t  *buffer);
-
-/* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
-HB_INTERNAL void
-hb_ot_layout_position_finish_offsets (hb_font_t    *font,
-                                      hb_buffer_t  *buffer);
-
-
-
-/*
- * hb_ot_layout_t
- */
-
-namespace OT {
-  struct BASE;
-  struct COLR;
-  struct CPAL;
-  struct GDEF;
-  struct GSUB;
-  struct GPOS;
-  struct MATH;
-  struct fvar;
-  struct avar;
-}
-
-namespace AAT {
-  struct ankr;
-  struct kerx;
-  struct morx;
-  struct trak;
-}
-
-struct hb_ot_layout_lookup_accelerator_t
-{
-  template <typename TLookup>
-  inline void init (const TLookup &lookup)
-  {
-    digest.init ();
-    lookup.add_coverage (&digest);
-  }
-
-  inline void fini (void)
-  {
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return digest.may_have (g);
-  }
-
-  private:
-  hb_set_digest_t digest;
-};
-
-struct hb_ot_layout_t
-{
-  hb_blob_t *gdef_blob;
-  hb_blob_t *gsub_blob;
-  hb_blob_t *gpos_blob;
-
-  const struct OT::GDEF *gdef;
-  const struct OT::GSUB *gsub;
-  const struct OT::GPOS *gpos;
-
-  /* TODO Move the following out of this struct. */
-  OT::hb_table_lazy_loader_t<struct OT::BASE> base;
-  OT::hb_table_lazy_loader_t<struct OT::MATH> math;
-  OT::hb_table_lazy_loader_t<struct OT::fvar> fvar;
-  OT::hb_table_lazy_loader_t<struct OT::avar> avar;
-
-  unsigned int gsub_lookup_count;
-  unsigned int gpos_lookup_count;
-
-  hb_ot_layout_lookup_accelerator_t *gsub_accels;
-  hb_ot_layout_lookup_accelerator_t *gpos_accels;
-};
-
-
-HB_INTERNAL hb_ot_layout_t *
-_hb_ot_layout_create (hb_face_t *face);
-
-HB_INTERNAL void
-_hb_ot_layout_destroy (hb_ot_layout_t *layout);
-
-
-#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
-
-
-/*
- * Buffer var routines.
- */
-
-/* buffer var allocations, used during the entire shaping process */
-#define unicode_props()         var2.u16[0]
-
-/* buffer var allocations, used during the GSUB/GPOS processing */
-#define glyph_props()           var1.u16[0] /* GDEF glyph properties */
-#define lig_props()             var1.u8[2] /* GSUB/GPOS ligature tracking */
-#define syllable()              var1.u8[3] /* GSUB/GPOS shaping boundaries */
-
-
-/* Loop over syllables. Based on foreach_cluster(). */
-#define foreach_syllable(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_syllable (buffer, start))
-
-static inline unsigned int
-_next_syllable (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  unsigned int syllable = info[start].syllable();
-  while (++start < count && syllable == info[start].syllable())
-    ;
-
-  return start;
-}
-
-
-/* unicode_props */
-
-/* Design:
- * unicode_props() is a two-byte number.  The low byte includes:
- * - General_Category: 5 bits.
- * - A bit each for:
- *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
- *   * Whether it's one of the three Mongolian Free Variation Selectors,
- *     CGJ, or other characters that are hidden but should not be ignored
- *     like most other Default_Ignorable()s do during matching.
- *   * One free bit right now.
- *
- * The high-byte has different meanings, switched by the Gen-Cat:
- * - For Mn,Mc,Me: the modified Combining_Class.
- * - For Cf: whether it's ZWJ, ZWNJ, or something else.
- * - For Ws: index of which space character this is, if space fallback
- *   is needed, ie. we don't set this by default, only if asked to.
- */
-
-enum hb_unicode_props_flags_t {
-  UPROPS_MASK_GEN_CAT   = 0x001Fu,
-  UPROPS_MASK_IGNORABLE = 0x0020u,
-  UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3,
-                                    * or TAG characters */
-
-  /* If GEN_CAT=FORMAT, top byte masks: */
-  UPROPS_MASK_Cf_ZWJ    = 0x0100u,
-  UPROPS_MASK_Cf_ZWNJ   = 0x0200u
-};
-HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
-
-static inline void
-_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
-{
-  hb_unicode_funcs_t *unicode = buffer->unicode;
-  unsigned int u = info->codepoint;
-  unsigned int gen_cat = (unsigned int) unicode->general_category (u);
-  unsigned int props = gen_cat;
-
-  if (u >= 0x80)
-  {
-    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
-    if (unlikely (unicode->is_default_ignorable (u)))
-    {
-      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
-      props |=  UPROPS_MASK_IGNORABLE;
-      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
-      else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
-      /* Mongolian Free Variation Selectors need to be remembered
-       * because although we need to hide them like default-ignorables,
-       * they need to non-ignorable during shaping.  This is similar to
-       * what we do for joiners in Indic-like shapers, but since the
-       * FVSes are GC=Mn, we have use a separate bit to remember them.
-       * Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/234 */
-      else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
-      /* TAG characters need similar treatment. Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/463 */
-      else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
-      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
-       * https://github.com/harfbuzz/harfbuzz/issues/554 */
-      else if (unlikely (u == 0x034Fu))
-      {
-        buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
-        props |= UPROPS_MASK_HIDDEN;
-      }
-    }
-    else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
-    {
-      /* The above check is just an optimization to let in only things we need further
-       * processing on. */
-
-      /* Only Mn and Mc can have non-zero ccc:
-       * https://unicode.org/policies/stability_policy.html#Property_Value
-       * """
-       * Canonical_Combining_Class, General_Category
-       * All characters other than those with General_Category property values
-       * Spacing_Mark (Mc) and Nonspacing_Mark (Mn) have the Canonical_Combining_Class
-       * property value 0.
-       * 1.1.5+
-       * """
-       *
-       * Also, all Mn's that are Default_Ignorable, have ccc=0, hence
-       * the "else if".
-       */
-      props |= unicode->modified_combining_class (info->codepoint)<<8;
-
-      /* Recategorize emoji skin-tone modifiers as Unicode mark, so they
-       * behave correctly in non-native directionality.  They originally
-       * are MODIFIER_SYMBOL.  Fixes:
-       * https://github.com/harfbuzz/harfbuzz/issues/169
-       */
-      if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
-      {
-        props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
-      }
-    }
-  }
-
-  info->unicode_props() = props;
-}
-
-static inline void
-_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
-                                     hb_unicode_general_category_t gen_cat)
-{
-  /* Clears top-byte. */
-  info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
-}
-
-static inline hb_unicode_general_category_t
-_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
-{
-  return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
-}
-
-static inline bool
-_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
-{
-  return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
-}
-static inline void
-_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
-                                             unsigned int modified_class)
-{
-  if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
-    return;
-  info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
-}
-static inline unsigned int
-_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
-}
-
-
-/* Loop over grapheme. Based on foreach_cluster(). */
-#define foreach_grapheme(buffer, start, end) \
-  for (unsigned int \
-       _count = buffer->len, \
-       start = 0, end = _count ? _next_grapheme (buffer, 0) : 0; \
-       start < _count; \
-       start = end, end = _next_grapheme (buffer, start))
-
-static inline unsigned int
-_next_grapheme (hb_buffer_t *buffer, unsigned int start)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  while (++start < count && _hb_glyph_info_is_unicode_mark (&info[start]))
-    ;
-
-  return start;
-}
-
-
-#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
-
-static inline bool
-_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_get_general_category (info) ==
-         HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
-}
-static inline void
-_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
-{
-  if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
-    return;
-  info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
-}
-static inline hb_unicode_funcs_t::space_t
-_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_space (info) ?
-         (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
-         hb_unicode_funcs_t::NOT_SPACE;
-}
-
-static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
-
-static inline hb_bool_t
-_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
-{
-  return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
-         !_hb_glyph_info_ligated (info);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
-{
-  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
-          == UPROPS_MASK_IGNORABLE) &&
-         !_hb_glyph_info_ligated (info);
-}
-static inline void
-_hb_glyph_info_unhide (hb_glyph_info_t *info)
-{
-  info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
-}
-
-static inline bool
-_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_get_general_category (info) ==
-         HB_UNICODE_GENERAL_CATEGORY_FORMAT;
-}
-static inline hb_bool_t
-_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
-}
-static inline hb_bool_t
-_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
-}
-static inline void
-_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
-{
-  if (!_hb_glyph_info_is_unicode_format (info))
-    return;
-  info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
-}
-
-/* lig_props: aka lig_id / lig_comp
- *
- * When a ligature is formed:
- *
- *   - The ligature glyph and any marks in between all the same newly allocated
- *     lig_id,
- *   - The ligature glyph will get lig_num_comps set to the number of components
- *   - The marks get lig_comp > 0, reflecting which component of the ligature
- *     they were applied to.
- *   - This is used in GPOS to attach marks to the right component of a ligature
- *     in MarkLigPos,
- *   - Note that when marks are ligated together, much of the above is skipped
- *     and the current lig_id reused.
- *
- * When a multiple-substitution is done:
- *
- *   - All resulting glyphs will have lig_id = 0,
- *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
- *   - This is used in GPOS to attach marks to the first component of a
- *     multiple substitution in MarkBasePos.
- *
- * The numbers are also used in GPOS to do mark-to-mark positioning only
- * to marks that belong to the same component of the same ligature.
- */
-
-static inline void
-_hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
-{
-  info->lig_props() = 0;
-}
-
-#define IS_LIG_BASE 0x10
-
-static inline void
-_hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
-                                           unsigned int lig_id,
-                                           unsigned int lig_num_comps)
-{
-  info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
-}
-
-static inline void
-_hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
-                                       unsigned int lig_id,
-                                       unsigned int lig_comp)
-{
-  info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
-}
-
-static inline void
-_hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
-{
-  _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
-{
-  return info->lig_props() >> 5;
-}
-
-static inline bool
-_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
-{
-  return !!(info->lig_props() & IS_LIG_BASE);
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
-{
-  if (_hb_glyph_info_ligated_internal (info))
-    return 0;
-  else
-    return info->lig_props() & 0x0F;
-}
-
-static inline unsigned int
-_hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
-{
-  if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
-      _hb_glyph_info_ligated_internal (info))
-    return info->lig_props() & 0x0F;
-  else
-    return 1;
-}
-
-static inline uint8_t
-_hb_allocate_lig_id (hb_buffer_t *buffer) {
-  uint8_t lig_id = buffer->next_serial () & 0x07;
-  if (unlikely (!lig_id))
-    lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
-  return lig_id;
-}
-
-/* glyph_props: */
-
-static inline void
-_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
-{
-  info->glyph_props() = props;
-}
-
-static inline unsigned int
-_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
-{
-  return info->glyph_props();
-}
-
-static inline bool
-_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
-}
-
-static inline bool
-_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
-}
-
-static inline bool
-_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
-}
-
-static inline bool
-_hb_glyph_info_substituted (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
-}
-
-static inline bool
-_hb_glyph_info_ligated (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
-}
-
-static inline bool
-_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
-{
-  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
-}
-
-static inline bool
-_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
-{
-  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
-}
-
-static inline void
-_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
-{
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
-                           HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
-}
-
-static inline void
-_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
-{
-  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
-}
-
-
-/* Allocation / deallocation. */
-
-static inline void
-_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
-}
-
-static inline void
-_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
-  HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
-  HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
-}
-
-static inline void
-_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
-}
-
-static inline void
-_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
-{
-  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
-  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
-  HB_BUFFER_ASSERT_VAR (buffer, syllable);
-}
-
-/* Make sure no one directly touches our props... */
-#undef unicode_props0
-#undef unicode_props1
-#undef lig_props
-#undef glyph_props
-
-#endif /* HB_OT_LAYOUT_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -28,232 +28,201 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type-private.hh"
-#include "hb-ot-layout-private.hh"
-#include "hb-ot-map-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-layout.hh"
+#include "hb-ot-face.hh"
+#include "hb-ot-map.hh"
+#include "hb-map.hh"
 
+#include "hb-ot-kern-table.hh"
+#include "hb-ot-gasp-table.hh" // Just so we compile it; unused otherwise.
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
+#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-name-table.hh"
+#include "hb-ot-os2-table.hh"
 
-// Just so we compile them; unused otherwise:
-#include "hb-ot-layout-base-table.hh"
-#include "hb-ot-layout-jstf-table.hh"
-#include "hb-ot-color-colr-table.hh"
-#include "hb-ot-color-cpal-table.hh"
-#include "hb-ot-color-sbix-table.hh"
-#include "hb-ot-color-svg-table.hh"
-#include "hb-ot-name-table.hh"
-#include "hb-map-private.hh"
+#include "hb-aat-layout-lcar-table.hh"
+#include "hb-aat-layout-morx-table.hh"
+
+
+/**
+ * SECTION:hb-ot-layout
+ * @title: hb-ot-layout
+ * @short_description: OpenType Layout
+ * @include: hb-ot.h
+ *
+ * Functions for querying OpenType Layout features in the font face.
+ **/
 
 
-hb_ot_layout_t *
-_hb_ot_layout_create (hb_face_t *face)
-{
-  hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
-  if (unlikely (!layout))
-    return nullptr;
-
-  layout->gdef_blob = OT::Sanitizer<OT::GDEF>().sanitize (face->reference_table (HB_OT_TAG_GDEF));
-  layout->gdef = layout->gdef_blob->as<OT::GDEF> ();
+/*
+ * kern
+ */
 
-  layout->gsub_blob = OT::Sanitizer<OT::GSUB>().sanitize (face->reference_table (HB_OT_TAG_GSUB));
-  layout->gsub = layout->gsub_blob->as<OT::GSUB> ();
-
-  layout->gpos_blob = OT::Sanitizer<OT::GPOS>().sanitize (face->reference_table (HB_OT_TAG_GPOS));
-  layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
-
-  layout->math.init (face);
-  layout->fvar.init (face);
-  layout->avar.init (face);
+bool
+hb_ot_layout_has_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_data ();
+}
 
-  {
-    /*
-     * The ugly business of blacklisting individual fonts' tables happen here!
-     * See this thread for why we finally had to bend in and do this:
-     * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-     */
-    unsigned int gdef_len = layout->gdef_blob->length;
-    unsigned int gsub_len = layout->gsub_blob->length;
-    unsigned int gpos_len = layout->gpos_blob->length;
-    if (0
-      /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
-      || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
-      || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
-      || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
-      || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len)
-      /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
-      || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len)
-      /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
-      || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len)
-    )
-    {
-      /* In certain versions of Times New Roman Italic and Bold Italic,
-       * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong
-       * glyph class 3 (mark) in GDEF.  Nuke the GDEF to avoid zero-width
-       * double-quote.  See:
-       * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-       */
-     if (3 == layout->gdef->get_glyph_class (5))
-       layout->gdef = &Null(OT::GDEF);
-    }
-    else if (0
-      /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
-      || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len)
-      /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
-      || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len)
-      /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
-      || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len)
-      /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
-      || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len)
-      /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (964 == gdef_len && 60072 == gpos_len && 23836 == gsub_len)
-      /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (976 == gdef_len && 61456 == gpos_len && 23832 == gsub_len)
-      /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
-      || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len)
-      /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
-      || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len)
-      /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (1006 == gdef_len && 61346 == gpos_len && 24576 == gsub_len)
-      /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
-      || (1018 == gdef_len && 62828 == gpos_len && 24572 == gsub_len)
-      /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
-      || (1006 == gdef_len && 61352 == gpos_len && 24576 == gsub_len)
-      /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
-      || (1018 == gdef_len && 62834 == gpos_len && 24572 == gsub_len)
-      /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
-      || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len)
-      /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
-      || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len)
-      /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
-      || (180 == gdef_len && 7254 == gpos_len && 13054 == gsub_len)
-      /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
-      || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len)
-      /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
-      || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len)
-      /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
-      /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
-      || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len)
-      /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
-      /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
-      || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len)
-      /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
-      || (1058 == gdef_len && 11818 == gpos_len && 47032 == gsub_len)
-      /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
-      || (1046 == gdef_len && 12600 == gpos_len && 47030 == gsub_len)
-      /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
-      || (1058 == gdef_len && 16770 == gpos_len && 71796 == gsub_len)
-      /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
-      || (1046 == gdef_len && 17862 == gpos_len && 71790 == gsub_len)
-      /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
-      || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len)
-      /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
-      || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len)
-      /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
-      || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len)
-      /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
-      || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len)
-      /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
-       *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
-      || (1004 == gdef_len && 14836 == gpos_len && 59092 == gsub_len)
-    )
-    {
-      /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks
-       * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya,
-       * and the version of Cantarell shipped by Ubuntu 16.04.
-       * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing.
-       * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
-       *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
-       *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
-       */
-      layout->gdef = &Null(OT::GDEF);
-    }
-  }
+bool
+hb_ot_layout_has_machine_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_state_machine ();
+}
 
-  layout->gsub_lookup_count = layout->gsub->get_lookup_count ();
-  layout->gpos_lookup_count = layout->gpos->get_lookup_count ();
-
-  layout->gsub_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
-  layout->gpos_accels = (hb_ot_layout_lookup_accelerator_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_ot_layout_lookup_accelerator_t));
-
-  if (unlikely ((layout->gsub_lookup_count && !layout->gsub_accels) ||
-                (layout->gpos_lookup_count && !layout->gpos_accels)))
-  {
-    _hb_ot_layout_destroy (layout);
-    return nullptr;
-  }
-
-  for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-    layout->gsub_accels[i].init (layout->gsub->get_lookup (i));
-  for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-    layout->gpos_accels[i].init (layout->gpos->get_lookup (i));
-
-  return layout;
+bool
+hb_ot_layout_has_cross_kerning (hb_face_t *face)
+{
+  return face->table.kern->has_cross_stream ();
 }
 
 void
-_hb_ot_layout_destroy (hb_ot_layout_t *layout)
+hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
+                   hb_font_t *font,
+                   hb_buffer_t  *buffer)
 {
-  if (layout->gsub_accels)
-    for (unsigned int i = 0; i < layout->gsub_lookup_count; i++)
-      layout->gsub_accels[i].fini ();
-  if (layout->gpos_accels)
-    for (unsigned int i = 0; i < layout->gpos_lookup_count; i++)
-      layout->gpos_accels[i].fini ();
+  hb_blob_t *blob = font->face->table.kern.get_blob ();
+  const AAT::kern& kern = *blob->as<AAT::kern> ();
 
-  free (layout->gsub_accels);
-  free (layout->gpos_accels);
+  AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
 
-  hb_blob_destroy (layout->gdef_blob);
-  hb_blob_destroy (layout->gsub_blob);
-  hb_blob_destroy (layout->gpos_blob);
-
-  layout->math.fini ();
-  layout->fvar.fini ();
-  layout->avar.fini ();
-
-  free (layout);
+  kern.apply (&c);
 }
 
-// static inline const OT::BASE&
-// _get_base (hb_face_t *face)
-// {
-//   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::BASE);
-//   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-//   return *(layout->base.get ());
-// }
-
-static inline const OT::GDEF&
-_get_gdef (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF);
-  return *hb_ot_layout_from_face (face)->gdef;
-}
-static inline const OT::GSUB&
-_get_gsub (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GSUB);
-  return *hb_ot_layout_from_face (face)->gsub;
-}
-static inline const OT::GPOS&
-_get_gpos (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GPOS);
-  return *hb_ot_layout_from_face (face)->gpos;
-}
 
 /*
  * GDEF
  */
 
+bool
+OT::GDEF::is_blacklisted (hb_blob_t *blob,
+                          hb_face_t *face) const
+{
+  /* The ugly business of blacklisting individual fonts' tables happen here!
+   * See this thread for why we finally had to bend in and do this:
+   * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
+   *
+   * In certain versions of Times New Roman Italic and Bold Italic,
+   * ASCII double quotation mark U+0022 has wrong glyph class 3 (mark)
+   * in GDEF.  Many versions of Tahoma have bad GDEF tables that
+   * incorrectly classify some spacing marks such as certain IPA
+   * symbols as glyph class 3. So do older versions of Microsoft
+   * Himalaya, and the version of Cantarell shipped by Ubuntu 16.04.
+   *
+   * Nuke the GDEF tables of to avoid unwanted width-zeroing.
+   *
+   * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
+   *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
+   *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
+   */
+#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z))
+  switch ENCODE(blob->length,
+                face->table.GSUB->table.get_length (),
+                face->table.GPOS->table.get_length ())
+  {
+    /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
+    case ENCODE (442, 2874, 42038):
+    /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
+    case ENCODE (430, 2874, 40662):
+    /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
+    case ENCODE (442, 2874, 39116):
+    /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
+    case ENCODE (430, 2874, 39374):
+    /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
+    case ENCODE (490, 3046, 41638):
+    /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
+    case ENCODE (478, 3046, 41902):
+    /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
+    case ENCODE (898, 12554, 46470):
+    /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
+    case ENCODE (910, 12566, 47732):
+    /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
+    case ENCODE (928, 23298, 59332):
+    /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
+    case ENCODE (940, 23310, 60732):
+    /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (964, 23836, 60072):
+    /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (976, 23832, 61456):
+    /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
+    case ENCODE (994, 24474, 60336):
+    /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
+    case ENCODE (1006, 24470, 61740):
+    /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (1006, 24576, 61346):
+    /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
+    case ENCODE (1018, 24572, 62828):
+    /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
+    case ENCODE (1006, 24576, 61352):
+    /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
+    case ENCODE (1018, 24572, 62834):
+    /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
+    case ENCODE (832, 7324, 47162):
+    /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
+    case ENCODE (844, 7302, 45474):
+    /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
+    case ENCODE (180, 13054, 7254):
+    /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
+    case ENCODE (192, 12638, 7254):
+    /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
+    case ENCODE (192, 12690, 7254):
+    /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
+    /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
+    case ENCODE (188, 248, 3852):
+    /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
+    /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
+    case ENCODE (188, 264, 3426):
+    /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
+    case ENCODE (1058, 47032, 11818):
+    /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
+    case ENCODE (1046, 47030, 12600):
+    /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
+    case ENCODE (1058, 71796, 16770):
+    /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
+    case ENCODE (1046, 71790, 17862):
+    /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
+    case ENCODE (1046, 71788, 17112):
+    /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
+    case ENCODE (1058, 71794, 17514):
+    /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
+    case ENCODE (1330, 109904, 57938):
+    /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
+    case ENCODE (1330, 109904, 58972):
+    /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
+     *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
+    case ENCODE (1004, 59092, 14836):
+      return true;
+#undef ENCODE
+  }
+  return false;
+}
+
+static void
+_hb_ot_layout_set_glyph_props (hb_font_t *font,
+                               hb_buffer_t *buffer)
+{
+  _hb_buffer_assert_gsubgpos_vars (buffer);
+
+  const OT::GDEF &gdef = *font->face->table.GDEF->table;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
+    _hb_glyph_info_clear_lig_props (&buffer->info[i]);
+    buffer->info[i].syllable() = 0;
+  }
+}
+
+/* Public API */
+
 hb_bool_t
 hb_ot_layout_has_glyph_classes (hb_face_t *face)
 {
-  return _get_gdef (face).has_glyph_classes ();
+  return face->table.GDEF->table->has_glyph_classes ();
 }
 
 /**
@@ -265,7 +234,7 @@
 hb_ot_layout_get_glyph_class (hb_face_t      *face,
                               hb_codepoint_t  glyph)
 {
-  return (hb_ot_layout_glyph_class_t) _get_gdef (face).get_glyph_class (glyph);
+  return (hb_ot_layout_glyph_class_t) face->table.GDEF->table->get_glyph_class (glyph);
 }
 
 /**
@@ -278,7 +247,7 @@
                                   hb_ot_layout_glyph_class_t  klass,
                                   hb_set_t                   *glyphs /* OUT */)
 {
-  return _get_gdef (face).get_glyphs_in_class (klass, glyphs);
+  return face->table.GDEF->table->get_glyphs_in_class (klass, glyphs);
 }
 
 unsigned int
@@ -288,7 +257,10 @@
                                 unsigned int   *point_count /* IN/OUT */,
                                 unsigned int   *point_array /* OUT */)
 {
-  return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array);
+  return face->table.GDEF->table->get_attach_points (glyph,
+                                                     start_offset,
+                                                     point_count,
+                                                     point_array);
 }
 
 unsigned int
@@ -299,7 +271,15 @@
                                   unsigned int   *caret_count /* IN/OUT */,
                                   hb_position_t  *caret_array /* OUT */)
 {
-  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+  unsigned int result_caret_count = 0;
+  unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array);
+  if (result)
+  {
+    if (caret_count) *caret_count = result_caret_count;
+  }
+  else
+    result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
+  return result;
 }
 
 
@@ -307,13 +287,45 @@
  * GSUB/GPOS
  */
 
+bool
+OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
+                          hb_face_t *face) const
+{
+  /* Mac OS X prefers morx over GSUB.  It also ships with various Indic fonts,
+   * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
+   * GSUB/GPOS tables.  Some have GSUB with zero scripts, those are ignored by
+   * our morx/GSUB preference code.  But if GSUB has non-zero scripts, we tend
+   * to prefer it over morx because we want to be consistent with other OpenType
+   * shapers.
+   *
+   * To work around broken Indic Mac system fonts, we ignore GSUB table if
+   * OS/2 VendorId is 'MUTF' and font has morx table as well.
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1410
+   * https://github.com/harfbuzz/harfbuzz/issues/1348
+   * https://github.com/harfbuzz/harfbuzz/issues/1391
+   */
+  if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') &&
+                face->table.morx->has_data ()))
+    return true;
+
+  return false;
+}
+
+bool
+OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
+                          hb_face_t *face HB_UNUSED) const
+{
+  return false;
+}
+
 static const OT::GSUBGPOS&
 get_gsubgpos_table (hb_face_t *face,
                     hb_tag_t   table_tag)
 {
   switch (table_tag) {
-    case HB_OT_TAG_GSUB: return _get_gsub (face);
-    case HB_OT_TAG_GPOS: return _get_gpos (face);
+    case HB_OT_TAG_GSUB: return *face->table.GSUB->table;
+    case HB_OT_TAG_GPOS: return *face->table.GPOS->table;
     default:             return Null(OT::GSUBGPOS);
   }
 }
@@ -324,7 +336,7 @@
                                     hb_tag_t      table_tag,
                                     unsigned int  start_offset,
                                     unsigned int *script_count /* IN/OUT */,
-                                    hb_tag_t     *script_tags /* OUT */)
+                                    hb_tag_t     *script_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
 
@@ -370,17 +382,36 @@
                                   unsigned int   *script_index,
                                   hb_tag_t       *chosen_script)
 {
+  const hb_tag_t *t;
+  for (t = script_tags; *t; t++);
+  return hb_ot_layout_table_select_script (face, table_tag, t - script_tags, script_tags, script_index, chosen_script);
+}
+
+/**
+ * hb_ot_layout_table_select_script:
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_table_select_script (hb_face_t      *face,
+                                  hb_tag_t        table_tag,
+                                  unsigned int    script_count,
+                                  const hb_tag_t *script_tags,
+                                  unsigned int   *script_index  /* OUT */,
+                                  hb_tag_t       *chosen_script /* OUT */)
+{
   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), "");
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+  unsigned int i;
 
-  while (*script_tags)
+  for (i = 0; i < script_count; i++)
   {
-    if (g.find_script_index (*script_tags, script_index)) {
+    if (g.find_script_index (script_tags[i], script_index))
+    {
       if (chosen_script)
-        *chosen_script = *script_tags;
+        *chosen_script = script_tags[i];
       return true;
     }
-    script_tags++;
   }
 
   /* try finding 'DFLT' */
@@ -416,14 +447,14 @@
                                      hb_tag_t      table_tag,
                                      unsigned int  start_offset,
                                      unsigned int *feature_count /* IN/OUT */,
-                                     hb_tag_t     *feature_tags /* OUT */)
+                                     hb_tag_t     *feature_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
 
   return g.get_feature_tags (start_offset, feature_count, feature_tags);
 }
 
-hb_bool_t
+bool
 hb_ot_layout_table_find_feature (hb_face_t    *face,
                                  hb_tag_t      table_tag,
                                  hb_tag_t      feature_tag,
@@ -452,7 +483,7 @@
                                        unsigned int  script_index,
                                        unsigned int  start_offset,
                                        unsigned int *language_count /* IN/OUT */,
-                                       hb_tag_t     *language_tags /* OUT */)
+                                       hb_tag_t     *language_tags  /* OUT */)
 {
   const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
 
@@ -466,13 +497,38 @@
                                    hb_tag_t      language_tag,
                                    unsigned int *language_index)
 {
+  return hb_ot_layout_script_select_language (face,
+                                              table_tag,
+                                              script_index,
+                                              1,
+                                              &language_tag,
+                                              language_index);
+}
+
+/**
+ * hb_ot_layout_script_select_language:
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_script_select_language (hb_face_t      *face,
+                                     hb_tag_t        table_tag,
+                                     unsigned int    script_index,
+                                     unsigned int    language_count,
+                                     const hb_tag_t *language_tags,
+                                     unsigned int   *language_index /* OUT */)
+{
   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX), "");
   const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
+  unsigned int i;
 
-  if (s.find_lang_sys_index (language_tag, language_index))
-    return true;
+  for (i = 0; i < language_count; i++)
+  {
+    if (s.find_lang_sys_index (language_tags[i], language_index))
+      return true;
+  }
 
-  /* try with 'dflt'; MS site has had typos and many fonts use it now :( */
+  /* try finding 'dflt' */
   if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
     return false;
 
@@ -524,7 +580,7 @@
                                            unsigned int  script_index,
                                            unsigned int  language_index,
                                            unsigned int  start_offset,
-                                           unsigned int *feature_count /* IN/OUT */,
+                                           unsigned int *feature_count   /* IN/OUT */,
                                            unsigned int *feature_indexes /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
@@ -540,7 +596,7 @@
                                         unsigned int  language_index,
                                         unsigned int  start_offset,
                                         unsigned int *feature_count /* IN/OUT */,
-                                        hb_tag_t     *feature_tags /* OUT */)
+                                        hb_tag_t     *feature_tags  /* OUT */)
 {
   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
   const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
@@ -594,7 +650,7 @@
                                   hb_tag_t      table_tag,
                                   unsigned int  feature_index,
                                   unsigned int  start_offset,
-                                  unsigned int *lookup_count /* IN/OUT */,
+                                  unsigned int *lookup_count   /* IN/OUT */,
                                   unsigned int *lookup_indexes /* OUT */)
 {
   return hb_ot_layout_feature_with_variations_get_lookups (face,
@@ -615,156 +671,174 @@
 hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
                                      hb_tag_t      table_tag)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return 0;
-  switch (table_tag)
-  {
-    case HB_OT_TAG_GSUB:
-    {
-      return hb_ot_layout_from_face (face)->gsub_lookup_count;
-    }
-    case HB_OT_TAG_GPOS:
-    {
-      return hb_ot_layout_from_face (face)->gpos_lookup_count;
-    }
-  }
-  return 0;
+  return get_gsubgpos_table (face, table_tag).get_lookup_count ();
 }
 
-static void
-_hb_ot_layout_collect_lookups_lookups (hb_face_t      *face,
-                                       hb_tag_t        table_tag,
-                                       unsigned int    feature_index,
-                                       hb_set_t       *lookup_indexes /* OUT */)
+
+struct hb_collect_features_context_t
 {
-  unsigned int lookup_indices[32];
-  unsigned int offset, len;
+  hb_collect_features_context_t (hb_face_t       *face,
+                                 hb_tag_t         table_tag,
+                                 hb_set_t        *feature_indexes_)
+    : g (get_gsubgpos_table (face, table_tag)),
+      feature_indexes (feature_indexes_),
+      script_count(0),langsys_count(0) {}
+
+  bool visited (const OT::Script &s)
+  {
+    /* We might have Null() object here.  Don't want to involve
+     * that in the memoize.  So, detect empty objects and return. */
+    if (unlikely (!s.has_default_lang_sys () &&
+                  !s.get_lang_sys_count ()))
+      return true;
+
+    if (script_count++ > HB_MAX_SCRIPTS)
+      return true;
 
-  offset = 0;
-  do {
-    len = ARRAY_LENGTH (lookup_indices);
-    hb_ot_layout_feature_get_lookups (face,
-                                      table_tag,
-                                      feature_index,
-                                      offset, &len,
-                                      lookup_indices);
+    return visited (s, visited_script);
+  }
+  bool visited (const OT::LangSys &l)
+  {
+    /* We might have Null() object here.  Don't want to involve
+     * that in the memoize.  So, detect empty objects and return. */
+    if (unlikely (!l.has_required_feature () &&
+                  !l.get_feature_count ()))
+      return true;
+
+    if (langsys_count++ > HB_MAX_LANGSYS)
+      return true;
+
+    return visited (l, visited_langsys);
+  }
 
-    for (unsigned int i = 0; i < len; i++)
-      lookup_indexes->add (lookup_indices[i]);
+  private:
+  template <typename T>
+  bool visited (const T &p, hb_set_t &visited_set)
+  {
+    hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) &p - (uintptr_t) &g);
+     if (visited_set.has (delta))
+      return true;
 
-    offset += len;
-  } while (len == ARRAY_LENGTH (lookup_indices));
-}
+    visited_set.add (delta);
+    return false;
+  }
+
+  public:
+  const OT::GSUBGPOS &g;
+  hb_set_t           *feature_indexes;
+
+  private:
+  hb_set_t visited_script;
+  hb_set_t visited_langsys;
+  unsigned int script_count;
+  unsigned int langsys_count;
+};
 
 static void
-_hb_ot_layout_collect_lookups_features (hb_face_t      *face,
-                                        hb_tag_t        table_tag,
-                                        unsigned int    script_index,
-                                        unsigned int    language_index,
-                                        const hb_tag_t *features,
-                                        hb_set_t       *lookup_indexes /* OUT */)
+langsys_collect_features (hb_collect_features_context_t *c,
+                          const OT::LangSys  &l,
+                          const hb_tag_t     *features)
 {
+  if (c->visited (l)) return;
+
   if (!features)
   {
-    unsigned int required_feature_index;
-    if (hb_ot_layout_language_get_required_feature (face,
-                                                    table_tag,
-                                                    script_index,
-                                                    language_index,
-                                                    &required_feature_index,
-                                                    nullptr))
-      _hb_ot_layout_collect_lookups_lookups (face,
-                                             table_tag,
-                                             required_feature_index,
-                                             lookup_indexes);
-
-    /* All features */
-    unsigned int feature_indices[32];
-    unsigned int offset, len;
+    /* All features. */
+    if (l.has_required_feature ())
+      c->feature_indexes->add (l.get_required_feature_index ());
 
-    offset = 0;
-    do {
-      len = ARRAY_LENGTH (feature_indices);
-      hb_ot_layout_language_get_feature_indexes (face,
-                                                 table_tag,
-                                                 script_index,
-                                                 language_index,
-                                                 offset, &len,
-                                                 feature_indices);
-
-      for (unsigned int i = 0; i < len; i++)
-        _hb_ot_layout_collect_lookups_lookups (face,
-                                               table_tag,
-                                               feature_indices[i],
-                                               lookup_indexes);
-
-      offset += len;
-    } while (len == ARRAY_LENGTH (feature_indices));
+    l.add_feature_indexes_to (c->feature_indexes);
   }
   else
   {
+    /* Ugh. Any faster way? */
     for (; *features; features++)
     {
-      unsigned int feature_index;
-      if (hb_ot_layout_language_find_feature (face,
-                                              table_tag,
-                                              script_index,
-                                              language_index,
-                                              *features,
-                                              &feature_index))
-        _hb_ot_layout_collect_lookups_lookups (face,
-                                               table_tag,
-                                               feature_index,
-                                               lookup_indexes);
+      hb_tag_t feature_tag = *features;
+      unsigned int num_features = l.get_feature_count ();
+      for (unsigned int i = 0; i < num_features; i++)
+      {
+        unsigned int feature_index = l.get_feature_index (i);
+
+        if (feature_tag == c->g.get_feature_tag (feature_index))
+        {
+          c->feature_indexes->add (feature_index);
+          break;
+        }
+      }
     }
   }
 }
 
 static void
-_hb_ot_layout_collect_lookups_languages (hb_face_t      *face,
-                                         hb_tag_t        table_tag,
-                                         unsigned int    script_index,
-                                         const hb_tag_t *languages,
-                                         const hb_tag_t *features,
-                                         hb_set_t       *lookup_indexes /* OUT */)
+script_collect_features (hb_collect_features_context_t *c,
+                         const OT::Script   &s,
+                         const hb_tag_t *languages,
+                         const hb_tag_t *features)
 {
-  _hb_ot_layout_collect_lookups_features (face,
-                                          table_tag,
-                                          script_index,
-                                          HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
-                                          features,
-                                          lookup_indexes);
+  if (c->visited (s)) return;
 
   if (!languages)
   {
-    /* All languages */
-    unsigned int count = hb_ot_layout_script_get_language_tags (face,
-                                                                table_tag,
-                                                                script_index,
-                                                                0, nullptr, nullptr);
+    /* All languages. */
+    if (s.has_default_lang_sys ())
+      langsys_collect_features (c,
+                                s.get_default_lang_sys (),
+                                features);
+
+    unsigned int count = s.get_lang_sys_count ();
     for (unsigned int language_index = 0; language_index < count; language_index++)
-      _hb_ot_layout_collect_lookups_features (face,
-                                              table_tag,
-                                              script_index,
-                                              language_index,
-                                              features,
-                                              lookup_indexes);
+      langsys_collect_features (c,
+                                s.get_lang_sys (language_index),
+                                features);
   }
   else
   {
     for (; *languages; languages++)
     {
       unsigned int language_index;
-      if (hb_ot_layout_script_find_language (face,
-                                             table_tag,
-                                             script_index,
-                                             *languages,
-                                             &language_index))
-        _hb_ot_layout_collect_lookups_features (face,
-                                                table_tag,
-                                                script_index,
-                                                language_index,
-                                                features,
-                                                lookup_indexes);
+      if (s.find_lang_sys_index (*languages, &language_index))
+        langsys_collect_features (c,
+                                  s.get_lang_sys (language_index),
+                                  features);
+    }
+  }
+}
+
+/**
+ * hb_ot_layout_collect_features:
+ *
+ * Since: 1.8.5
+ **/
+void
+hb_ot_layout_collect_features (hb_face_t      *face,
+                               hb_tag_t        table_tag,
+                               const hb_tag_t *scripts,
+                               const hb_tag_t *languages,
+                               const hb_tag_t *features,
+                               hb_set_t       *feature_indexes /* OUT */)
+{
+  hb_collect_features_context_t c (face, table_tag, feature_indexes);
+  if (!scripts)
+  {
+    /* All scripts. */
+    unsigned int count = c.g.get_script_count ();
+    for (unsigned int script_index = 0; script_index < count; script_index++)
+      script_collect_features (&c,
+                               c.g.get_script (script_index),
+                               languages,
+                               features);
+  }
+  else
+  {
+    for (; *scripts; scripts++)
+    {
+      unsigned int script_index;
+      if (c.g.find_script_index (*scripts, &script_index))
+        script_collect_features (&c,
+                                 c.g.get_script (script_index),
+                                 languages,
+                                 features);
     }
   }
 }
@@ -782,37 +856,14 @@
                               const hb_tag_t *features,
                               hb_set_t       *lookup_indexes /* OUT */)
 {
-  if (!scripts)
-  {
-    /* All scripts */
-    unsigned int count = hb_ot_layout_table_get_script_tags (face,
-                                                             table_tag,
-                                                             0, nullptr, nullptr);
-    for (unsigned int script_index = 0; script_index < count; script_index++)
-      _hb_ot_layout_collect_lookups_languages (face,
-                                               table_tag,
-                                               script_index,
-                                               languages,
-                                               features,
-                                               lookup_indexes);
-  }
-  else
-  {
-    for (; *scripts; scripts++)
-    {
-      unsigned int script_index;
-      if (hb_ot_layout_table_find_script (face,
-                                          table_tag,
-                                          *scripts,
-                                          &script_index))
-        _hb_ot_layout_collect_lookups_languages (face,
-                                                 table_tag,
-                                                 script_index,
-                                                 languages,
-                                                 features,
-                                                 lookup_indexes);
-    }
-  }
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_set_t feature_indexes;
+  hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
+
+  for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
+       hb_set_next (&feature_indexes, &feature_index);)
+    g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
 }
 
 /**
@@ -824,13 +875,11 @@
 hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
                                     hb_tag_t      table_tag,
                                     unsigned int  lookup_index,
-                                    hb_set_t     *glyphs_before, /* OUT. May be nullptr */
-                                    hb_set_t     *glyphs_input,  /* OUT. May be nullptr */
-                                    hb_set_t     *glyphs_after,  /* OUT. May be nullptr */
-                                    hb_set_t     *glyphs_output  /* OUT. May be nullptr */)
+                                    hb_set_t     *glyphs_before, /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_input,  /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_after,  /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_output  /* OUT.  May be NULL */)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return;
-
   OT::hb_collect_glyphs_context_t c (face,
                                      glyphs_before,
                                      glyphs_input,
@@ -841,13 +890,13 @@
   {
     case HB_OT_TAG_GSUB:
     {
-      const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
+      const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
       l.collect_glyphs (&c);
       return;
     }
     case HB_OT_TAG_GPOS:
     {
-      const OT::PosLookup& l = hb_ot_layout_from_face (face)->gpos->get_lookup (lookup_index);
+      const OT::PosLookup& l = face->table.GPOS->table->get_lookup (lookup_index);
       l.collect_glyphs (&c);
       return;
     }
@@ -894,7 +943,7 @@
 hb_bool_t
 hb_ot_layout_has_substitution (hb_face_t *face)
 {
-  return &_get_gsub (face) != &Null(OT::GSUB);
+  return face->table.GSUB->table->has_data ();
 }
 
 /**
@@ -909,29 +958,82 @@
                                       unsigned int          glyphs_length,
                                       hb_bool_t             zero_context)
 {
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return false;
-  return hb_ot_layout_lookup_would_substitute_fast (face, lookup_index, glyphs, glyphs_length, zero_context);
+  return hb_ot_layout_lookup_would_substitute_fast (face,
+                                                    lookup_index,
+                                                    glyphs, glyphs_length,
+                                                    zero_context);
 }
 
-hb_bool_t
+bool
 hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
                                            unsigned int          lookup_index,
                                            const hb_codepoint_t *glyphs,
                                            unsigned int          glyphs_length,
-                                           hb_bool_t             zero_context)
+                                           bool                  zero_context)
 {
-  if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false;
+  if (unlikely (lookup_index >= face->table.GSUB->lookup_count)) return false;
   OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
 
-  const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index);
+  const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
+
+  return l.would_apply (&c, &face->table.GSUB->accels[lookup_index]);
+}
 
-  return l.would_apply (&c, &hb_ot_layout_from_face (face)->gsub_accels[lookup_index]);
+void
+hb_ot_layout_substitute_start (hb_font_t    *font,
+                               hb_buffer_t  *buffer)
+{
+_hb_ot_layout_set_glyph_props (font, buffer);
 }
 
 void
-hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer)
+hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
+                                    bool (*filter) (const hb_glyph_info_t *info))
 {
-  OT::GSUB::substitute_start (font, buffer);
+  /* Merge clusters and delete filtered glyphs.
+   * NOTE! We can't use out-buffer as we have positioning data. */
+  unsigned int j = 0;
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
+  hb_glyph_position_t *pos = buffer->pos;
+  for (unsigned int i = 0; i < count; i++)
+  {
+    if (filter (&info[i]))
+    {
+      /* Merge clusters.
+       * Same logic as buffer->delete_glyph(), but for in-place removal. */
+
+      unsigned int cluster = info[i].cluster;
+      if (i + 1 < count && cluster == info[i + 1].cluster)
+        continue; /* Cluster survives; do nothing. */
+
+      if (j)
+      {
+        /* Merge cluster backward. */
+        if (cluster < info[j - 1].cluster)
+        {
+          unsigned int mask = info[i].mask;
+          unsigned int old_cluster = info[j - 1].cluster;
+          for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
+            buffer->set_cluster (info[k - 1], cluster, mask);
+        }
+        continue;
+      }
+
+      if (i + 1 < count)
+        buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
+
+      continue;
+    }
+
+    if (j != i)
+    {
+      info[j] = info[i];
+      pos[j] = pos[i];
+    }
+    j++;
+  }
+  buffer->len = j;
 }
 
 /**
@@ -944,10 +1046,10 @@
                                         unsigned int  lookup_index,
                                         hb_set_t     *glyphs)
 {
-  hb_auto_t<hb_map_t> done_lookups;
+  hb_map_t done_lookups;
   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
 
-  const OT::SubstLookup& l = _get_gsub (face).get_lookup (lookup_index);
+  const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
 
   l.closure (&c, lookup_index);
 }
@@ -965,10 +1067,11 @@
                                          const hb_set_t *lookups,
                                          hb_set_t       *glyphs)
 {
-  hb_auto_t<hb_map_t> done_lookups;
+  hb_map_t done_lookups;
   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
-  const OT::GSUB& gsub = _get_gsub (face);
+  const OT::GSUB& gsub = *face->table.GSUB->table;
 
+  unsigned int iteration_count = 0;
   unsigned int glyphs_length;
   do
   {
@@ -983,7 +1086,8 @@
       for (unsigned int i = 0; i < gsub.get_lookup_count (); i++)
         gsub.get_lookup (i).closure (&c, i);
     }
-  } while (glyphs_length != glyphs->get_population ());
+  } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
+           glyphs_length != glyphs->get_population ());
 }
 
 /*
@@ -993,7 +1097,7 @@
 hb_bool_t
 hb_ot_layout_has_positioning (hb_face_t *face)
 {
-  return &_get_gpos (face) != &Null(OT::GPOS);
+  return face->table.GPOS->table->has_data ();
 }
 
 void
@@ -1020,14 +1124,14 @@
  * Since: 0.9.10
  **/
 hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t    *face,
-                              unsigned int *design_size,       /* OUT.  May be nullptr */
-                              unsigned int *subfamily_id,      /* OUT.  May be nullptr */
-                              unsigned int *subfamily_name_id, /* OUT.  May be nullptr */
-                              unsigned int *range_start,       /* OUT.  May be nullptr */
-                              unsigned int *range_end          /* OUT.  May be nullptr */)
+hb_ot_layout_get_size_params (hb_face_t       *face,
+                              unsigned int    *design_size,       /* OUT.  May be NULL */
+                              unsigned int    *subfamily_id,      /* OUT.  May be NULL */
+                              hb_ot_name_id_t *subfamily_name_id, /* OUT.  May be NULL */
+                              unsigned int    *range_start,       /* OUT.  May be NULL */
+                              unsigned int    *range_end          /* OUT.  May be NULL */)
 {
-  const OT::GPOS &gpos = _get_gpos (face);
+  const OT::GPOS &gpos = *face->table.GPOS->table;
   const hb_tag_t tag = HB_TAG ('s','i','z','e');
 
   unsigned int num_features = gpos.get_feature_count ();
@@ -1040,30 +1144,152 @@
 
       if (params.designSize)
       {
-#define PARAM(a, A) if (a) *a = params.A
-        PARAM (design_size, designSize);
-        PARAM (subfamily_id, subfamilyID);
-        PARAM (subfamily_name_id, subfamilyNameID);
-        PARAM (range_start, rangeStart);
-        PARAM (range_end, rangeEnd);
-#undef PARAM
+        if (design_size) *design_size = params.designSize;
+        if (subfamily_id) *subfamily_id = params.subfamilyID;
+        if (subfamily_name_id) *subfamily_name_id = params.subfamilyNameID;
+        if (range_start) *range_start = params.rangeStart;
+        if (range_end) *range_end = params.rangeEnd;
 
         return true;
       }
     }
   }
 
-#define PARAM(a, A) if (a) *a = 0
-  PARAM (design_size, designSize);
-  PARAM (subfamily_id, subfamilyID);
-  PARAM (subfamily_name_id, subfamilyNameID);
-  PARAM (range_start, rangeStart);
-  PARAM (range_end, rangeEnd);
-#undef PARAM
+  if (design_size) *design_size = 0;
+  if (subfamily_id) *subfamily_id = 0;
+  if (subfamily_name_id) *subfamily_name_id = HB_OT_NAME_ID_INVALID;
+  if (range_start) *range_start = 0;
+  if (range_end) *range_end = 0;
 
   return false;
 }
 
+/**
+ * hb_ot_layout_feature_get_name_ids:
+ * @face: #hb_face_t to work upon
+ * @table_tag: table tag to query, "GSUB" or "GPOS".
+ * @feature_index: index of feature to query.
+ * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ *            for a user-interface label for this feature. (May be NULL.)
+ * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
+ *              that an application can use for tooltip text for this
+ *              feature. (May be NULL.)
+ * @sample_id: (out) (allow-none): The ‘name’ table name ID that specifies sample text
+ *             that illustrates the effect of this feature. (May be NULL.)
+ * @num_named_parameters: (out) (allow-none):  Number of named parameters. (May be zero.)
+ * @first_param_id: (out) (allow-none): The first ‘name’ table name ID used to specify
+ *                  strings for user-interface labels for the feature
+ *                  parameters. (Must be zero if numParameters is zero.)
+ *
+ * Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
+ * "Character Variant" ('cvXX') features.
+ *
+ * Return value: true if data found, false otherwise
+ *
+ * Since: 2.0.0
+ **/
+hb_bool_t
+hb_ot_layout_feature_get_name_ids (hb_face_t       *face,
+                                   hb_tag_t         table_tag,
+                                   unsigned int     feature_index,
+                                   hb_ot_name_id_t *label_id,             /* OUT.  May be NULL */
+                                   hb_ot_name_id_t *tooltip_id,           /* OUT.  May be NULL */
+                                   hb_ot_name_id_t *sample_id,            /* OUT.  May be NULL */
+                                   unsigned int    *num_named_parameters, /* OUT.  May be NULL */
+                                   hb_ot_name_id_t *first_param_id        /* OUT.  May be NULL */)
+{
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_tag_t feature_tag = g.get_feature_tag (feature_index);
+  const OT::Feature &f = g.get_feature (feature_index);
+
+  const OT::FeatureParams &feature_params = f.get_feature_params ();
+  if (&feature_params != &Null (OT::FeatureParams))
+  {
+    const OT::FeatureParamsStylisticSet& ss_params =
+      feature_params.get_stylistic_set_params (feature_tag);
+    if (&ss_params != &Null (OT::FeatureParamsStylisticSet)) /* ssXX */
+    {
+      if (label_id) *label_id = ss_params.uiNameID;
+      // ssXX features don't have the rest
+      if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
+      if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
+      if (num_named_parameters) *num_named_parameters = 0;
+      if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
+      return true;
+    }
+    const OT::FeatureParamsCharacterVariants& cv_params =
+      feature_params.get_character_variants_params (feature_tag);
+    if (&cv_params != &Null (OT::FeatureParamsCharacterVariants)) /* cvXX */
+    {
+      if (label_id) *label_id = cv_params.featUILableNameID;
+      if (tooltip_id) *tooltip_id = cv_params.featUITooltipTextNameID;
+      if (sample_id) *sample_id = cv_params.sampleTextNameID;
+      if (num_named_parameters) *num_named_parameters = cv_params.numNamedParameters;
+      if (first_param_id) *first_param_id = cv_params.firstParamUILabelNameID;
+      return true;
+    }
+  }
+
+  if (label_id) *label_id = HB_OT_NAME_ID_INVALID;
+  if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
+  if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
+  if (num_named_parameters) *num_named_parameters = 0;
+  if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
+  return false;
+}
+
+/**
+ * hb_ot_layout_feature_get_characters:
+ * @face: #hb_face_t to work upon
+ * @table_tag: table tag to query, "GSUB" or "GPOS".
+ * @feature_index: index of feature to query.
+ * @start_offset: In case the resulting char_count was equal to its input value, there
+ *                is a chance there were more characters on the tag so this API can be
+ *                called with an offset till resulting char_count gets to a number
+ *                lower than input buffer (or consider using just a bigger buffer for
+ *                one shot copying).
+ * @char_count: (inout) (allow-none): The count of characters for which this feature
+ *              provides glyph variants. (May be zero.)
+ * @characters: (out caller-allocates) (array length=char_count): A buffer pointer. The Unicode codepoints
+ *              of the characters for which this feature provides glyph variants.
+ *
+ * Fetches characters listed by designer under feature parameters for "Character
+ * Variant" ("cvXX") features.
+ *
+ * Return value: Number of total sample characters in the cvXX feature.
+ *
+ * Since: 2.0.0
+ **/
+unsigned int
+hb_ot_layout_feature_get_characters (hb_face_t      *face,
+                                     hb_tag_t        table_tag,
+                                     unsigned int    feature_index,
+                                     unsigned int    start_offset,
+                                     unsigned int   *char_count, /* IN/OUT.  May be NULL */
+                                     hb_codepoint_t *characters  /* OUT.     May be NULL */)
+{
+  const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
+
+  hb_tag_t feature_tag = g.get_feature_tag (feature_index);
+  const OT::Feature &f = g.get_feature (feature_index);
+
+  const OT::FeatureParams &feature_params = f.get_feature_params ();
+
+  const OT::FeatureParamsCharacterVariants& cv_params =
+    feature_params.get_character_variants_params(feature_tag);
+
+  unsigned int len = 0;
+  if (char_count && characters && start_offset < cv_params.characters.len)
+  {
+    len = MIN (cv_params.characters.len - start_offset, *char_count);
+    for (unsigned int i = 0; i < len; ++i)
+      characters[i] = cv_params.characters[start_offset + i];
+  }
+  if (char_count) *char_count = len;
+  return cv_params.characters.len;
+}
+
 
 /*
  * Parts of different types are implemented here such that they have direct
@@ -1073,86 +1299,36 @@
 
 struct GSUBProxy
 {
-  static const unsigned int table_index = 0;
-  static const bool inplace = false;
+  static constexpr unsigned table_index = 0u;
+  static constexpr bool inplace = false;
   typedef OT::SubstLookup Lookup;
 
   GSUBProxy (hb_face_t *face) :
-    table (*hb_ot_layout_from_face (face)->gsub),
-    accels (hb_ot_layout_from_face (face)->gsub_accels) {}
+    table (*face->table.GSUB->table),
+    accels (face->table.GSUB->accels) {}
 
   const OT::GSUB &table;
-  const hb_ot_layout_lookup_accelerator_t *accels;
+  const OT::hb_ot_layout_lookup_accelerator_t *accels;
 };
 
 struct GPOSProxy
 {
-  static const unsigned int table_index = 1;
-  static const bool inplace = true;
+  static constexpr unsigned table_index = 1u;
+  static constexpr bool inplace = true;
   typedef OT::PosLookup Lookup;
 
   GPOSProxy (hb_face_t *face) :
-    table (*hb_ot_layout_from_face (face)->gpos),
-    accels (hb_ot_layout_from_face (face)->gpos_accels) {}
+    table (*face->table.GPOS->table),
+    accels (face->table.GPOS->accels) {}
 
   const OT::GPOS &table;
-  const hb_ot_layout_lookup_accelerator_t *accels;
+  const OT::hb_ot_layout_lookup_accelerator_t *accels;
 };
 
 
-struct hb_get_subtables_context_t :
-       OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
-{
-  template <typename Type>
-  static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
-  {
-    const Type *typed_obj = (const Type *) obj;
-    return typed_obj->apply (c);
-  }
-
-  typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
-
-  struct hb_applicable_t
-  {
-    inline void init (const void *obj_, hb_apply_func_t apply_func_)
-    {
-      obj = obj_;
-      apply_func = apply_func_;
-    }
-
-    inline bool apply (OT::hb_ot_apply_context_t *c) const { return apply_func (obj, c); }
-
-    private:
-    const void *obj;
-    hb_apply_func_t apply_func;
-  };
-
-  typedef hb_auto_t<hb_vector_t<hb_applicable_t> > array_t;
-
-  /* Dispatch interface. */
-  inline const char *get_name (void) { return "GET_SUBTABLES"; }
-  template <typename T>
-  inline return_t dispatch (const T &obj)
-  {
-    hb_applicable_t *entry = array.push();
-    entry->init (&obj, apply_to<T>);
-    return HB_VOID;
-  }
-  static return_t default_return_value (void) { return HB_VOID; }
-  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
-
-  hb_get_subtables_context_t (array_t &array_) :
-                              array (array_),
-                              debug_depth (0) {}
-
-  array_t &array;
-  unsigned int debug_depth;
-};
-
 static inline bool
 apply_forward (OT::hb_ot_apply_context_t *c,
-               const hb_ot_layout_lookup_accelerator_t &accel,
-               const hb_get_subtables_context_t::array_t &subtables)
+               const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   bool ret = false;
   hb_buffer_t *buffer = c->buffer;
@@ -1163,12 +1339,7 @@
         (buffer->cur().mask & c->lookup_mask) &&
         c->check_glyph_property (&buffer->cur(), c->lookup_props))
      {
-       for (unsigned int i = 0; i < subtables.len; i++)
-         if (subtables[i].apply (c))
-         {
-           applied = true;
-           break;
-         }
+       applied = accel.apply (c);
      }
 
     if (applied)
@@ -1181,8 +1352,7 @@
 
 static inline bool
 apply_backward (OT::hb_ot_apply_context_t *c,
-               const hb_ot_layout_lookup_accelerator_t &accel,
-               const hb_get_subtables_context_t::array_t &subtables)
+               const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   bool ret = false;
   hb_buffer_t *buffer = c->buffer;
@@ -1191,14 +1361,8 @@
     if (accel.may_have (buffer->cur().codepoint) &&
         (buffer->cur().mask & c->lookup_mask) &&
         c->check_glyph_property (&buffer->cur(), c->lookup_props))
-    {
-     for (unsigned int i = 0; i < subtables.len; i++)
-       if (subtables[i].apply (c))
-       {
-         ret = true;
-         break;
-       }
-    }
+     ret |= accel.apply (c);
+
     /* The reverse lookup doesn't "advance" cursor (for good reason). */
     buffer->idx--;
 
@@ -1211,7 +1375,7 @@
 static inline void
 apply_string (OT::hb_ot_apply_context_t *c,
               const typename Proxy::Lookup &lookup,
-              const hb_ot_layout_lookup_accelerator_t &accel)
+              const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   hb_buffer_t *buffer = c->buffer;
 
@@ -1220,19 +1384,15 @@
 
   c->set_lookup_props (lookup.get_props ());
 
-  hb_get_subtables_context_t::array_t subtables;
-  hb_get_subtables_context_t c_get_subtables (subtables);
-  lookup.dispatch (&c_get_subtables);
-
   if (likely (!lookup.is_reverse ()))
   {
     /* in/out forward substitution/positioning */
-    if (Proxy::table_index == 0)
+    if (Proxy::table_index == 0u)
       buffer->clear_output ();
     buffer->idx = 0;
 
     bool ret;
-    ret = apply_forward (c, accel, subtables);
+    ret = apply_forward (c, accel);
     if (ret)
     {
       if (!Proxy::inplace)
@@ -1244,11 +1404,11 @@
   else
   {
     /* in-place backward substitution/positioning */
-    if (Proxy::table_index == 0)
+    if (Proxy::table_index == 0u)
       buffer->remove_output ();
     buffer->idx = buffer->len - 1;
 
-    apply_backward (c, accel, subtables);
+    apply_backward (c, accel);
   }
 }
 
@@ -1263,7 +1423,7 @@
   OT::hb_ot_apply_context_t c (table_index, font, buffer);
   c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
 
-  for (unsigned int stage_index = 0; stage_index < stages[table_index].len; stage_index++) {
+  for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++) {
     const stage_map_t *stage = &stages[table_index][stage_index];
     for (; i < stage->last_lookup; i++)
     {
@@ -1273,6 +1433,11 @@
       c.set_lookup_mask (lookups[table_index][i].mask);
       c.set_auto_zwj (lookups[table_index][i].auto_zwj);
       c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
+      if (lookups[table_index][i].random)
+      {
+        c.set_random (true);
+        buffer->unsafe_to_break_all ();
+      }
       apply_string<Proxy> (&c,
                            proxy.table.get_lookup (lookup_index),
                            proxy.accels[lookup_index]);
@@ -1302,31 +1467,65 @@
 void
 hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
                                 const OT::SubstLookup &lookup,
-                                const hb_ot_layout_lookup_accelerator_t &accel)
+                                const OT::hb_ot_layout_lookup_accelerator_t &accel)
 {
   apply_string<GSUBProxy> (c, lookup, accel);
 }
 
-
-
+#if 0
+static const OT::BASE& _get_base (hb_face_t *face)
+{
+  return *face->table.BASE;
+}
 
+hb_bool_t
+hb_ot_layout_get_baseline (hb_font_t               *font,
+                           hb_ot_layout_baseline_t  baseline,
+                           hb_direction_t           direction,
+                           hb_tag_t                 script_tag,
+                           hb_tag_t                 language_tag,
+                           hb_position_t           *coord        /* OUT.  May be NULL. */)
+{
+  const OT::BASE &base = _get_base (font->face);
+  bool result = base.get_baseline (font, baseline, direction, script_tag,
+                                   language_tag, coord);
+
+  /* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */
+  if (!result && coord) *coord = 0;
+
+  if (coord) *coord = font->em_scale_dir (*coord, direction);
+
+  return result;
+}
+
+/* To be moved to public header */
 /*
- * OT::BASE
+ * BASE
  */
 
-// /**
-//  * hb_ot_base_has_data:
-//  * @face: #hb_face_t to test
-//  *
-//  * This function allows to verify the presence of an OpenType BASE table on the
-//  * face.
-//  *
-//  * Return value: true if face has a BASE table, false otherwise
-//  *
-//  * Since: XXX
-//  **/
-// hb_bool_t
-// hb_ot_base_has_data (hb_face_t *face)
-// {
-//   return &_get_base (face) != &Null(OT::BASE);
-// }
+/**
+ * hb_ot_layout_baseline_t:
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags
+ *
+ * Since: DONTREPLACEME
+ */
+typedef enum {
+  HB_OT_LAYOUT_BASELINE_HANG = HB_TAG('h','a','n','g'),
+  HB_OT_LAYOUT_BASELINE_ICFB = HB_TAG('i','c','f','b'),
+  HB_OT_LAYOUT_BASELINE_ICFT = HB_TAG('i','c','f','t'),
+  HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'),
+  HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'),
+  HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'),
+  HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n')
+} hb_ot_layout_baseline_t;
+
+HB_EXTERN hb_bool_t
+hb_ot_layout_get_baseline (hb_font_t               *font,
+                           hb_ot_layout_baseline_t  baseline,
+                           hb_direction_t           direction,
+                           hb_tag_t                 script_tag,
+                           hb_tag_t                 language_tag,
+                           hb_position_t           *coord        /* OUT.  May be NULL. */);
+
+#endif
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.h	Tue Mar 26 09:05:10 2019 -0400
@@ -33,7 +33,7 @@
 
 #include "hb.h"
 
-#include "hb-ot-tag.h"
+#include "hb-ot-name.h"
 
 HB_BEGIN_DECLS
 
@@ -46,6 +46,47 @@
 
 
 /*
+ * Script & Language tags.
+ */
+
+#define HB_OT_TAG_DEFAULT_SCRIPT        HB_TAG ('D', 'F', 'L', 'T')
+#define HB_OT_TAG_DEFAULT_LANGUAGE      HB_TAG ('d', 'f', 'l', 't')
+
+/**
+ * HB_OT_MAX_TAGS_PER_SCRIPT:
+ *
+ * Since: 2.0.0
+ **/
+#define HB_OT_MAX_TAGS_PER_SCRIPT       3u
+/**
+ * HB_OT_MAX_TAGS_PER_LANGUAGE:
+ *
+ * Since: 2.0.0
+ **/
+#define HB_OT_MAX_TAGS_PER_LANGUAGE     3u
+
+HB_EXTERN void
+hb_ot_tags_from_script_and_language (hb_script_t   script,
+                                     hb_language_t language,
+                                     unsigned int *script_count /* IN/OUT */,
+                                     hb_tag_t     *script_tags /* OUT */,
+                                     unsigned int *language_count /* IN/OUT */,
+                                     hb_tag_t     *language_tags /* OUT */);
+
+HB_EXTERN hb_script_t
+hb_ot_tag_to_script (hb_tag_t tag);
+
+HB_EXTERN hb_language_t
+hb_ot_tag_to_language (hb_tag_t tag);
+
+HB_EXTERN void
+hb_ot_tags_to_script_and_language (hb_tag_t       script_tag,
+                                   hb_tag_t       language_tag,
+                                   hb_script_t   *script /* OUT */,
+                                   hb_language_t *language /* OUT */);
+
+
+/*
  * GDEF
  */
 
@@ -111,13 +152,13 @@
                                 hb_tag_t      script_tag,
                                 unsigned int *script_index);
 
-/* Like find_script, but takes zero-terminated array of scripts to test */
 HB_EXTERN hb_bool_t
-hb_ot_layout_table_choose_script (hb_face_t      *face,
+hb_ot_layout_table_select_script (hb_face_t      *face,
                                   hb_tag_t        table_tag,
+                                  unsigned int    script_count,
                                   const hb_tag_t *script_tags,
-                                  unsigned int   *script_index,
-                                  hb_tag_t       *chosen_script);
+                                  unsigned int   *script_index /* OUT */,
+                                  hb_tag_t       *chosen_script /* OUT */);
 
 HB_EXTERN unsigned int
 hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
@@ -135,11 +176,12 @@
                                        hb_tag_t     *language_tags /* OUT */);
 
 HB_EXTERN hb_bool_t
-hb_ot_layout_script_find_language (hb_face_t    *face,
-                                   hb_tag_t      table_tag,
-                                   unsigned int  script_index,
-                                   hb_tag_t      language_tag,
-                                   unsigned int *language_index);
+hb_ot_layout_script_select_language (hb_face_t      *face,
+                                     hb_tag_t        table_tag,
+                                     unsigned int    script_index,
+                                     unsigned int    language_count,
+                                     const hb_tag_t *language_tags,
+                                     unsigned int   *language_index /* OUT */);
 
 HB_EXTERN hb_bool_t
 hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
@@ -194,6 +236,13 @@
 hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
                                      hb_tag_t      table_tag);
 
+HB_EXTERN void
+hb_ot_layout_collect_features (hb_face_t      *face,
+                               hb_tag_t        table_tag,
+                               const hb_tag_t *scripts,
+                               const hb_tag_t *languages,
+                               const hb_tag_t *features,
+                               hb_set_t       *feature_indexes /* OUT */);
 
 HB_EXTERN void
 hb_ot_layout_collect_lookups (hb_face_t      *face,
@@ -207,10 +256,10 @@
 hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
                                     hb_tag_t      table_tag,
                                     unsigned int  lookup_index,
-                                    hb_set_t     *glyphs_before, /* OUT. May be NULL */
-                                    hb_set_t     *glyphs_input,  /* OUT. May be NULL */
-                                    hb_set_t     *glyphs_after,  /* OUT. May be NULL */
-                                    hb_set_t     *glyphs_output  /* OUT. May be NULL */);
+                                    hb_set_t     *glyphs_before, /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_input,  /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_after,  /* OUT.  May be NULL */
+                                    hb_set_t     *glyphs_output  /* OUT.  May be NULL */);
 
 #ifdef HB_NOT_IMPLEMENTED
 typedef struct
@@ -315,29 +364,32 @@
 /* Optical 'size' feature info.  Returns true if found.
  * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
 HB_EXTERN hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t    *face,
-                              unsigned int *design_size,       /* OUT.  May be NULL */
-                              unsigned int *subfamily_id,      /* OUT.  May be NULL */
-                              unsigned int *subfamily_name_id, /* OUT.  May be NULL */
-                              unsigned int *range_start,       /* OUT.  May be NULL */
-                              unsigned int *range_end          /* OUT.  May be NULL */);
+hb_ot_layout_get_size_params (hb_face_t       *face,
+                              unsigned int    *design_size,       /* OUT.  May be NULL */
+                              unsigned int    *subfamily_id,      /* OUT.  May be NULL */
+                              hb_ot_name_id_t *subfamily_name_id, /* OUT.  May be NULL */
+                              unsigned int    *range_start,       /* OUT.  May be NULL */
+                              unsigned int    *range_end          /* OUT.  May be NULL */);
 
 
-/*
- * BASE
- */
-#if 0
+HB_EXTERN hb_bool_t
+hb_ot_layout_feature_get_name_ids (hb_face_t       *face,
+                                   hb_tag_t         table_tag,
+                                   unsigned int     feature_index,
+                                   hb_ot_name_id_t *label_id             /* OUT.  May be NULL */,
+                                   hb_ot_name_id_t *tooltip_id           /* OUT.  May be NULL */,
+                                   hb_ot_name_id_t *sample_id            /* OUT.  May be NULL */,
+                                   unsigned int    *num_named_parameters /* OUT.  May be NULL */,
+                                   hb_ot_name_id_t *first_param_id       /* OUT.  May be NULL */);
 
-#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g')
-#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b')
-#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t')
-#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o')
-#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b')
-#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h')
-#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n')
 
-#endif
-
+HB_EXTERN unsigned int
+hb_ot_layout_feature_get_characters (hb_face_t      *face,
+                                     hb_tag_t        table_tag,
+                                     unsigned int    feature_index,
+                                     unsigned int    start_offset,
+                                     unsigned int   *char_count    /* IN/OUT.  May be NULL */,
+                                     hb_codepoint_t *characters    /* OUT.     May be NULL */);
 
 HB_END_DECLS
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-layout.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,612 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2012,2013  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_LAYOUT_HH
+#define HB_OT_LAYOUT_HH
+
+#include "hb.hh"
+
+#include "hb-font.hh"
+#include "hb-buffer.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-shape.hh"
+#include "hb-set-digest.hh"
+
+
+struct hb_ot_shape_plan_t;
+
+
+/*
+ * kern
+ */
+
+HB_INTERNAL bool
+hb_ot_layout_has_kerning (hb_face_t *face);
+
+HB_INTERNAL bool
+hb_ot_layout_has_machine_kerning (hb_face_t *face);
+
+HB_INTERNAL bool
+hb_ot_layout_has_cross_kerning (hb_face_t *face);
+
+HB_INTERNAL void
+hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
+                   hb_font_t *font,
+                   hb_buffer_t  *buffer);
+
+
+/* Private API corresponding to hb-ot-layout.h: */
+
+HB_INTERNAL bool
+hb_ot_layout_table_find_feature (hb_face_t    *face,
+                                 hb_tag_t      table_tag,
+                                 hb_tag_t      feature_tag,
+                                 unsigned int *feature_index);
+
+
+/*
+ * GDEF
+ */
+
+enum hb_ot_layout_glyph_props_flags_t
+{
+  /* The following three match LookupFlags::Ignore* numbers. */
+  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH   = 0x02u,
+  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE     = 0x04u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MARK         = 0x08u,
+
+  /* The following are used internally; not derived from GDEF. */
+  HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED  = 0x10u,
+  HB_OT_LAYOUT_GLYPH_PROPS_LIGATED      = 0x20u,
+  HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED   = 0x40u,
+
+  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE     = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
+                                          HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+                                          HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
+};
+HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
+
+
+/*
+ * GSUB/GPOS
+ */
+
+HB_INTERNAL bool
+hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
+                                           unsigned int          lookup_index,
+                                           const hb_codepoint_t *glyphs,
+                                           unsigned int          glyphs_length,
+                                           bool                  zero_context);
+
+
+/* Should be called before all the substitute_lookup's are done. */
+HB_INTERNAL void
+hb_ot_layout_substitute_start (hb_font_t    *font,
+                               hb_buffer_t  *buffer);
+
+HB_INTERNAL void
+hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
+                                    bool (*filter) (const hb_glyph_info_t *info));
+
+namespace OT {
+  struct hb_ot_apply_context_t;
+  struct SubstLookup;
+  struct hb_ot_layout_lookup_accelerator_t;
+}
+
+HB_INTERNAL void
+hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
+                                const OT::SubstLookup &lookup,
+                                const OT::hb_ot_layout_lookup_accelerator_t &accel);
+
+
+/* Should be called before all the position_lookup's are done. */
+HB_INTERNAL void
+hb_ot_layout_position_start (hb_font_t    *font,
+                             hb_buffer_t  *buffer);
+
+/* Should be called after all the position_lookup's are done, to fini advances. */
+HB_INTERNAL void
+hb_ot_layout_position_finish_advances (hb_font_t    *font,
+                                       hb_buffer_t  *buffer);
+
+/* Should be called after hb_ot_layout_position_finish_advances, to fini offsets. */
+HB_INTERNAL void
+hb_ot_layout_position_finish_offsets (hb_font_t    *font,
+                                      hb_buffer_t  *buffer);
+
+
+/*
+ * Buffer var routines.
+ */
+
+/* buffer var allocations, used during the entire shaping process */
+#define unicode_props()         var2.u16[0]
+
+/* buffer var allocations, used during the GSUB/GPOS processing */
+#define glyph_props()           var1.u16[0] /* GDEF glyph properties */
+#define lig_props()             var1.u8[2] /* GSUB/GPOS ligature tracking */
+#define syllable()              var1.u8[3] /* GSUB/GPOS shaping boundaries */
+
+
+/* Loop over syllables. Based on foreach_cluster(). */
+#define foreach_syllable(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _hb_next_syllable (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _hb_next_syllable (buffer, start))
+
+static inline unsigned int
+_hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  unsigned int syllable = info[start].syllable();
+  while (++start < count && syllable == info[start].syllable())
+    ;
+
+  return start;
+}
+
+
+/* unicode_props */
+
+/* Design:
+ * unicode_props() is a two-byte number.  The low byte includes:
+ * - General_Category: 5 bits.
+ * - A bit each for:
+ *   * Is it Default_Ignorable(); we have a modified Default_Ignorable().
+ *   * Whether it's one of the three Mongolian Free Variation Selectors,
+ *     CGJ, or other characters that are hidden but should not be ignored
+ *     like most other Default_Ignorable()s do during matching.
+ *   * Whether it's a grapheme continuation.
+ *
+ * The high-byte has different meanings, switched by the Gen-Cat:
+ * - For Mn,Mc,Me: the modified Combining_Class.
+ * - For Cf: whether it's ZWJ, ZWNJ, or something else.
+ * - For Ws: index of which space character this is, if space fallback
+ *   is needed, ie. we don't set this by default, only if asked to.
+ */
+
+enum hb_unicode_props_flags_t {
+  UPROPS_MASK_GEN_CAT   = 0x001Fu,
+  UPROPS_MASK_IGNORABLE = 0x0020u,
+  UPROPS_MASK_HIDDEN    = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3, or TAG characters */
+  UPROPS_MASK_CONTINUATION=0x0080u,
+
+  /* If GEN_CAT=FORMAT, top byte masks: */
+  UPROPS_MASK_Cf_ZWJ    = 0x0100u,
+  UPROPS_MASK_Cf_ZWNJ   = 0x0200u
+};
+HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
+
+static inline void
+_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
+{
+  hb_unicode_funcs_t *unicode = buffer->unicode;
+  unsigned int u = info->codepoint;
+  unsigned int gen_cat = (unsigned int) unicode->general_category (u);
+  unsigned int props = gen_cat;
+
+  if (u >= 0x80)
+  {
+    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
+
+    if (unlikely (unicode->is_default_ignorable (u)))
+    {
+      buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
+      props |=  UPROPS_MASK_IGNORABLE;
+      if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
+      else if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
+      /* Mongolian Free Variation Selectors need to be remembered
+       * because although we need to hide them like default-ignorables,
+       * they need to non-ignorable during shaping.  This is similar to
+       * what we do for joiners in Indic-like shapers, but since the
+       * FVSes are GC=Mn, we have use a separate bit to remember them.
+       * Fixes:
+       * https://github.com/harfbuzz/harfbuzz/issues/234 */
+      else if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_HIDDEN;
+      /* TAG characters need similar treatment. Fixes:
+       * https://github.com/harfbuzz/harfbuzz/issues/463 */
+      else if (unlikely (hb_in_range (u, 0xE0020u, 0xE007Fu))) props |= UPROPS_MASK_HIDDEN;
+      /* COMBINING GRAPHEME JOINER should not be skipped; at least some times.
+       * https://github.com/harfbuzz/harfbuzz/issues/554 */
+      else if (unlikely (u == 0x034Fu))
+      {
+        buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_CGJ;
+        props |= UPROPS_MASK_HIDDEN;
+      }
+    }
+
+    if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (gen_cat)))
+    {
+      props |= UPROPS_MASK_CONTINUATION;
+      props |= unicode->modified_combining_class (u)<<8;
+    }
+  }
+
+  info->unicode_props() = props;
+}
+
+static inline void
+_hb_glyph_info_set_general_category (hb_glyph_info_t *info,
+                                     hb_unicode_general_category_t gen_cat)
+{
+  /* Clears top-byte. */
+  info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
+}
+
+static inline hb_unicode_general_category_t
+_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
+{
+  return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
+}
+
+static inline bool
+_hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
+{
+  return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
+}
+static inline void
+_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
+                                             unsigned int modified_class)
+{
+  if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
+    return;
+  info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
+}
+static inline unsigned int
+_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
+}
+#define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
+
+static inline bool
+_hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_get_general_category (info) ==
+         HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
+}
+static inline void
+_hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
+{
+  if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
+    return;
+  info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
+}
+static inline hb_unicode_funcs_t::space_t
+_hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_space (info) ?
+         (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
+         hb_unicode_funcs_t::NOT_SPACE;
+}
+
+static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
+
+static inline bool
+_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
+{
+  return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
+         !_hb_glyph_info_ligated (info);
+}
+static inline bool
+_hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info)
+{
+  return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_HIDDEN))
+          == UPROPS_MASK_IGNORABLE) &&
+         !_hb_glyph_info_ligated (info);
+}
+static inline void
+_hb_glyph_info_unhide (hb_glyph_info_t *info)
+{
+  info->unicode_props() &= ~ UPROPS_MASK_HIDDEN;
+}
+
+static inline void
+_hb_glyph_info_set_continuation (hb_glyph_info_t *info)
+{
+  info->unicode_props() |= UPROPS_MASK_CONTINUATION;
+}
+static inline void
+_hb_glyph_info_reset_continuation (hb_glyph_info_t *info)
+{
+  info->unicode_props() &= ~ UPROPS_MASK_CONTINUATION;
+}
+static inline bool
+_hb_glyph_info_is_continuation (const hb_glyph_info_t *info)
+{
+  return info->unicode_props() & UPROPS_MASK_CONTINUATION;
+}
+/* Loop over grapheme. Based on foreach_cluster(). */
+#define foreach_grapheme(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _hb_next_grapheme (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _hb_next_grapheme (buffer, start))
+
+static inline unsigned int
+_hb_next_grapheme (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  while (++start < count && _hb_glyph_info_is_continuation (&info[start]))
+    ;
+
+  return start;
+}
+
+static inline bool
+_hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_get_general_category (info) ==
+         HB_UNICODE_GENERAL_CATEGORY_FORMAT;
+}
+static inline bool
+_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
+}
+static inline bool
+_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
+}
+static inline bool
+_hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
+}
+static inline void
+_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
+{
+  if (!_hb_glyph_info_is_unicode_format (info))
+    return;
+  info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
+}
+
+/* lig_props: aka lig_id / lig_comp
+ *
+ * When a ligature is formed:
+ *
+ *   - The ligature glyph and any marks in between all the same newly allocated
+ *     lig_id,
+ *   - The ligature glyph will get lig_num_comps set to the number of components
+ *   - The marks get lig_comp > 0, reflecting which component of the ligature
+ *     they were applied to.
+ *   - This is used in GPOS to attach marks to the right component of a ligature
+ *     in MarkLigPos,
+ *   - Note that when marks are ligated together, much of the above is skipped
+ *     and the current lig_id reused.
+ *
+ * When a multiple-substitution is done:
+ *
+ *   - All resulting glyphs will have lig_id = 0,
+ *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
+ *   - This is used in GPOS to attach marks to the first component of a
+ *     multiple substitution in MarkBasePos.
+ *
+ * The numbers are also used in GPOS to do mark-to-mark positioning only
+ * to marks that belong to the same component of the same ligature.
+ */
+
+static inline void
+_hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
+{
+  info->lig_props() = 0;
+}
+
+#define IS_LIG_BASE 0x10
+
+static inline void
+_hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
+                                           unsigned int lig_id,
+                                           unsigned int lig_num_comps)
+{
+  info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
+}
+
+static inline void
+_hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
+                                       unsigned int lig_id,
+                                       unsigned int lig_comp)
+{
+  info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
+}
+
+static inline void
+_hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
+{
+  _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
+{
+  return info->lig_props() >> 5;
+}
+
+static inline bool
+_hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
+{
+  return !!(info->lig_props() & IS_LIG_BASE);
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
+{
+  if (_hb_glyph_info_ligated_internal (info))
+    return 0;
+  else
+    return info->lig_props() & 0x0F;
+}
+
+static inline unsigned int
+_hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
+{
+  if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
+      _hb_glyph_info_ligated_internal (info))
+    return info->lig_props() & 0x0F;
+  else
+    return 1;
+}
+
+static inline uint8_t
+_hb_allocate_lig_id (hb_buffer_t *buffer) {
+  uint8_t lig_id = buffer->next_serial () & 0x07;
+  if (unlikely (!lig_id))
+    lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
+  return lig_id;
+}
+
+/* glyph_props: */
+
+static inline void
+_hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
+{
+  info->glyph_props() = props;
+}
+
+static inline unsigned int
+_hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
+{
+  return info->glyph_props();
+}
+
+static inline bool
+_hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
+}
+
+static inline bool
+_hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
+}
+
+static inline bool
+_hb_glyph_info_is_mark (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
+}
+
+static inline bool
+_hb_glyph_info_substituted (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+}
+
+static inline bool
+_hb_glyph_info_ligated (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
+}
+
+static inline bool
+_hb_glyph_info_multiplied (const hb_glyph_info_t *info)
+{
+  return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline bool
+_hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
+{
+  return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
+}
+
+static inline void
+_hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
+{
+  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
+                           HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
+}
+
+static inline void
+_hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
+{
+  info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
+}
+
+
+/* Allocation / deallocation. */
+
+static inline void
+_hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
+}
+
+static inline void
+_hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
+  HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
+  HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
+}
+
+static inline void
+_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
+  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
+}
+
+static inline void
+_hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
+{
+  HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
+  HB_BUFFER_ASSERT_VAR (buffer, lig_props);
+  HB_BUFFER_ASSERT_VAR (buffer, syllable);
+}
+
+/* Make sure no one directly touches our props... */
+#undef unicode_props0
+#undef unicode_props1
+#undef lig_props
+#undef glyph_props
+
+#endif /* HB_OT_LAYOUT_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/*
- * Copyright © 2009,2010  Red Hat, Inc.
- * Copyright © 2010,2011,2012,2013  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_MAP_PRIVATE_HH
-#define HB_OT_MAP_PRIVATE_HH
-
-#include "hb-buffer-private.hh"
-
-
-struct hb_ot_shape_plan_t;
-
-static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
-
-struct hb_ot_map_t
-{
-  friend struct hb_ot_map_builder_t;
-
-  public:
-
-  struct feature_map_t {
-    hb_tag_t tag; /* should be first for our bsearch to work */
-    unsigned int index[2]; /* GSUB/GPOS */
-    unsigned int stage[2]; /* GSUB/GPOS */
-    unsigned int shift;
-    hb_mask_t mask;
-    hb_mask_t _1_mask; /* mask for value=1, for quick access */
-    unsigned int needs_fallback : 1;
-    unsigned int auto_zwnj : 1;
-    unsigned int auto_zwj : 1;
-
-    inline int cmp (const hb_tag_t *tag_) const
-    { return *tag_ < tag ? -1 : *tag_ > tag ? 1 : 0; }
-  };
-
-  struct lookup_map_t {
-    unsigned short index;
-    unsigned short auto_zwnj : 1;
-    unsigned short auto_zwj : 1;
-    hb_mask_t mask;
-
-    static int cmp (const void *pa, const void *pb)
-    {
-      const lookup_map_t *a = (const lookup_map_t *) pa;
-      const lookup_map_t *b = (const lookup_map_t *) pb;
-      return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
-    }
-  };
-
-  typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
-
-  struct stage_map_t {
-    unsigned int last_lookup; /* Cumulative */
-    pause_func_t pause_func;
-  };
-
-  inline void init (void)
-  {
-    memset (this, 0, sizeof (*this));
-
-    features.init ();
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      lookups[table_index].init ();
-      stages[table_index].init ();
-    }
-  }
-  inline void fini (void)
-  {
-    features.fini ();
-    for (unsigned int table_index = 0; table_index < 2; table_index++)
-    {
-      lookups[table_index].fini ();
-      stages[table_index].fini ();
-    }
-  }
-
-  inline hb_mask_t get_global_mask (void) const { return global_mask; }
-
-  inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    if (shift) *shift = map ? map->shift : 0;
-    return map ? map->mask : 0;
-  }
-
-  inline bool needs_fallback (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->needs_fallback : false;
-  }
-
-  inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->_1_mask : 0;
-  }
-
-  inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
-  }
-
-  inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const {
-    const feature_map_t *map = features.bsearch (feature_tag);
-    return map ? map->stage[table_index] : (unsigned int) -1;
-  }
-
-  inline void get_stage_lookups (unsigned int table_index, unsigned int stage,
-                                 const struct lookup_map_t **plookups, unsigned int *lookup_count) const {
-    if (unlikely (stage == (unsigned int) -1)) {
-      *plookups = nullptr;
-      *lookup_count = 0;
-      return;
-    }
-    assert (stage <= stages[table_index].len);
-    unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
-    unsigned int end   = stage < stages[table_index].len ? stages[table_index][stage].last_lookup : lookups[table_index].len;
-    *plookups = end == start ? nullptr : &lookups[table_index][start];
-    *lookup_count = end - start;
-  }
-
-  HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
-  template <typename Proxy>
-  HB_INTERNAL inline void apply (const Proxy &proxy,
-                                 const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-  HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-  HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
-
-  public:
-  hb_tag_t chosen_script[2];
-  bool found_script[2];
-
-  private:
-
-  hb_mask_t global_mask;
-
-  hb_vector_t<feature_map_t, 8> features;
-  hb_vector_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
-  hb_vector_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */
-};
-
-enum hb_ot_map_feature_flags_t {
-  F_NONE                = 0x0000u,
-  F_GLOBAL              = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
-  F_HAS_FALLBACK        = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
-  F_MANUAL_ZWNJ         = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
-  F_MANUAL_ZWJ          = 0x0008u, /* Don't skip over ZWJ when matching **input**. */
-  F_GLOBAL_SEARCH       = 0x0010u  /* If feature not found in LangSys, look for it in global feature list and pick one. */
-};
-HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
-/* Macro version for where const is desired. */
-#define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r)))
-
-
-struct hb_ot_map_builder_t
-{
-  public:
-
-  HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
-                                   const hb_segment_properties_t *props_);
-
-  HB_INTERNAL ~hb_ot_map_builder_t (void);
-
-  HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value,
-                                hb_ot_map_feature_flags_t flags);
-
-  inline void add_global_bool_feature (hb_tag_t tag)
-  { add_feature (tag, 1, F_GLOBAL); }
-
-  inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
-  { add_pause (0, pause_func); }
-  inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
-  { add_pause (1, pause_func); }
-
-  HB_INTERNAL void compile (hb_ot_map_t  &m,
-                            const int    *coords,
-                            unsigned int  num_coords);
-
-  private:
-
-  HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
-                                unsigned int  table_index,
-                                unsigned int  feature_index,
-                                unsigned int  variations_index,
-                                hb_mask_t     mask,
-                                bool          auto_zwnj = true,
-                                bool          auto_zwj = true);
-
-  struct feature_info_t {
-    hb_tag_t tag;
-    unsigned int seq; /* sequence#, used for stable sorting only */
-    unsigned int max_value;
-    hb_ot_map_feature_flags_t flags;
-    unsigned int default_value; /* for non-global features, what should the unset glyphs take */
-    unsigned int stage[2]; /* GSUB/GPOS */
-
-    static int cmp (const void *pa, const void *pb)
-    {
-      const feature_info_t *a = (const feature_info_t *) pa;
-      const feature_info_t *b = (const feature_info_t *) pb;
-      return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
-             (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
-    }
-  };
-
-  struct stage_info_t {
-    unsigned int index;
-    hb_ot_map_t::pause_func_t pause_func;
-  };
-
-  HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func);
-
-  public:
-
-  hb_face_t *face;
-  hb_segment_properties_t props;
-
-  hb_tag_t chosen_script[2];
-  bool found_script[2];
-  unsigned int script_index[2], language_index[2];
-
-  private:
-
-  unsigned int current_stage[2]; /* GSUB/GPOS */
-  hb_vector_t<feature_info_t, 32> feature_infos;
-  hb_vector_t<stage_info_t, 8> stages[2]; /* GSUB/GPOS */
-};
-
-
-
-#endif /* HB_OT_MAP_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,14 +26,14 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-map-private.hh"
-
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-map.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-layout.hh"
 
 
 void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_out) const
 {
-  for (unsigned int i = 0; i < lookups[table_index].len; i++)
+  for (unsigned int i = 0; i < lookups[table_index].length; i++)
     hb_set_add (lookups_out, lookups[table_index][i].index);
 }
 
@@ -54,33 +54,35 @@
   /* Fetch script/language indices for GSUB/GPOS.  We need these later to skip
    * features not available in either table and not waste precious bits for them. */
 
-  hb_tag_t script_tags[3] = {HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE};
-  hb_tag_t language_tag;
+  unsigned int script_count = HB_OT_MAX_TAGS_PER_SCRIPT;
+  unsigned int language_count = HB_OT_MAX_TAGS_PER_LANGUAGE;
+  hb_tag_t script_tags[HB_OT_MAX_TAGS_PER_SCRIPT];
+  hb_tag_t language_tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
 
-  hb_ot_tags_from_script (props.script, &script_tags[0], &script_tags[1]);
-  language_tag = hb_ot_tag_from_language (props.language);
+  hb_ot_tags_from_script_and_language (props.script, props.language, &script_count, script_tags, &language_count, language_tags);
 
   for (unsigned int table_index = 0; table_index < 2; table_index++) {
     hb_tag_t table_tag = table_tags[table_index];
-    found_script[table_index] = (bool) hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &chosen_script[table_index]);
-    hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]);
+    found_script[table_index] = (bool) hb_ot_layout_table_select_script (face, table_tag, script_count, script_tags, &script_index[table_index], &chosen_script[table_index]);
+    hb_ot_layout_script_select_language (face, table_tag, script_index[table_index], language_count, language_tags, &language_index[table_index]);
   }
 }
 
-hb_ot_map_builder_t::~hb_ot_map_builder_t (void)
+hb_ot_map_builder_t::~hb_ot_map_builder_t ()
 {
   feature_infos.fini ();
   for (unsigned int table_index = 0; table_index < 2; table_index++)
     stages[table_index].fini ();
 }
 
-void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value,
-                                       hb_ot_map_feature_flags_t flags)
+void hb_ot_map_builder_t::add_feature (hb_tag_t tag,
+                                       hb_ot_map_feature_flags_t flags,
+                                       unsigned int value)
 {
+  if (unlikely (!tag)) return;
   feature_info_t *info = feature_infos.push();
-  if (unlikely (!tag)) return;
   info->tag = tag;
-  info->seq = feature_infos.len;
+  info->seq = feature_infos.length;
   info->max_value = value;
   info->flags = flags;
   info->default_value = (flags & F_GLOBAL) ? value : 0;
@@ -95,7 +97,8 @@
                                   unsigned int  variations_index,
                                   hb_mask_t     mask,
                                   bool          auto_zwnj,
-                                  bool          auto_zwj)
+                                  bool          auto_zwj,
+                                  bool          random)
 {
   unsigned int lookup_indices[32];
   unsigned int offset, len;
@@ -122,6 +125,7 @@
       lookup->index = lookup_indices[i];
       lookup->auto_zwnj = auto_zwnj;
       lookup->auto_zwj = auto_zwj;
+      lookup->random = random;
     }
 
     offset += len;
@@ -139,13 +143,12 @@
 }
 
 void
-hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
-                              const int    *coords,
-                              unsigned int  num_coords)
+hb_ot_map_builder_t::compile (hb_ot_map_t                  &m,
+                              const hb_ot_shape_plan_key_t &key)
 {
   static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
   unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
-  unsigned int global_bit_shift = _hb_popcount (HB_GLYPH_FLAG_DEFINED);
+  unsigned int global_bit_shift = hb_popcount (HB_GLYPH_FLAG_DEFINED);
 
   m.global_mask = global_bit_mask;
 
@@ -171,10 +174,11 @@
   }
 
   /* Sort features and merge duplicates */
+  if (feature_infos.length)
   {
     feature_infos.qsort ();
     unsigned int j = 0;
-    for (unsigned int i = 1; i < feature_infos.len; i++)
+    for (unsigned int i = 1; i < feature_infos.length; i++)
       if (feature_infos[i].tag != feature_infos[j].tag)
         feature_infos[++j] = feature_infos[i];
       else {
@@ -198,7 +202,7 @@
   /* Allocate bits now */
   unsigned int next_bit = global_bit_shift + 1;
 
-  for (unsigned int i = 0; i < feature_infos.len; i++)
+  for (unsigned int i = 0; i < feature_infos.length; i++)
   {
     const feature_info_t *info = &feature_infos[i];
 
@@ -208,8 +212,8 @@
       /* Uses the global bit */
       bits_needed = 0;
     else
-      /* Limit to 8 bits per feature. */
-      bits_needed = MIN(8u, _hb_bit_storage (info->max_value));
+      /* Limit bits per feature. */
+      bits_needed = MIN(HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
 
     if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
       continue; /* Feature disabled, or not enough bits. */
@@ -252,6 +256,7 @@
     map->stage[1] = info->stage[1];
     map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
     map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
+    map->random = !!(info->flags & F_RANDOM);
     if ((info->flags & F_GLOBAL) && info->max_value == 1) {
       /* Uses the global bit */
       map->shift = global_bit_shift;
@@ -276,13 +281,6 @@
   {
     /* Collect lookup indices for features */
 
-    unsigned int variations_index;
-    hb_ot_layout_table_find_feature_variations (face,
-                                                table_tags[table_index],
-                                                coords,
-                                                num_coords,
-                                                &variations_index);
-
     unsigned int stage_index = 0;
     unsigned int last_num_lookups = 0;
     for (unsigned stage = 0; stage < current_stage[table_index]; stage++)
@@ -291,25 +289,26 @@
           required_feature_stage[table_index] == stage)
         add_lookups (m, table_index,
                      required_feature_index[table_index],
-                     variations_index,
+                     key.variations_index[table_index],
                      global_bit_mask);
 
-      for (unsigned i = 0; i < m.features.len; i++)
+      for (unsigned i = 0; i < m.features.length; i++)
         if (m.features[i].stage[table_index] == stage)
           add_lookups (m, table_index,
                        m.features[i].index[table_index],
-                       variations_index,
+                       key.variations_index[table_index],
                        m.features[i].mask,
                        m.features[i].auto_zwnj,
-                       m.features[i].auto_zwj);
+                       m.features[i].auto_zwj,
+                       m.features[i].random);
 
       /* Sort lookups and merge duplicates */
-      if (last_num_lookups < m.lookups[table_index].len)
+      if (last_num_lookups < m.lookups[table_index].length)
       {
-        m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].len);
+        m.lookups[table_index].qsort (last_num_lookups, m.lookups[table_index].length);
 
         unsigned int j = last_num_lookups;
-        for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++)
+        for (unsigned int i = j + 1; i < m.lookups[table_index].length; i++)
           if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
             m.lookups[table_index][++j] = m.lookups[table_index][i];
           else
@@ -321,9 +320,9 @@
         m.lookups[table_index].shrink (j + 1);
       }
 
-      last_num_lookups = m.lookups[table_index].len;
+      last_num_lookups = m.lookups[table_index].length;
 
-      if (stage_index < stages[table_index].len && stages[table_index][stage_index].index == stage) {
+      if (stage_index < stages[table_index].length && stages[table_index][stage_index].index == stage) {
         hb_ot_map_t::stage_map_t *stage_map = m.stages[table_index].push ();
         stage_map->last_lookup = last_num_lookups;
         stage_map->pause_func = stages[table_index][stage_index].pause_func;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-map.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,284 @@
+/*
+ * Copyright © 2009,2010  Red Hat, Inc.
+ * Copyright © 2010,2011,2012,2013  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_MAP_HH
+#define HB_OT_MAP_HH
+
+#include "hb-buffer.hh"
+
+
+#define HB_OT_MAP_MAX_BITS 8u
+#define HB_OT_MAP_MAX_VALUE ((1u << HB_OT_MAP_MAX_BITS) - 1u)
+
+struct hb_ot_shape_plan_t;
+
+static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
+
+struct hb_ot_map_t
+{
+  friend struct hb_ot_map_builder_t;
+
+  public:
+
+  struct feature_map_t {
+    hb_tag_t tag; /* should be first for our bsearch to work */
+    unsigned int index[2]; /* GSUB/GPOS */
+    unsigned int stage[2]; /* GSUB/GPOS */
+    unsigned int shift;
+    hb_mask_t mask;
+    hb_mask_t _1_mask; /* mask for value=1, for quick access */
+    unsigned int needs_fallback : 1;
+    unsigned int auto_zwnj : 1;
+    unsigned int auto_zwj : 1;
+    unsigned int random : 1;
+
+    int cmp (const hb_tag_t tag_) const
+    { return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
+  };
+
+  struct lookup_map_t {
+    unsigned short index;
+    unsigned short auto_zwnj : 1;
+    unsigned short auto_zwj : 1;
+    unsigned short random : 1;
+    hb_mask_t mask;
+
+    static int cmp (const void *pa, const void *pb)
+    {
+      const lookup_map_t *a = (const lookup_map_t *) pa;
+      const lookup_map_t *b = (const lookup_map_t *) pb;
+      return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
+    }
+  };
+
+  typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
+
+  struct stage_map_t {
+    unsigned int last_lookup; /* Cumulative */
+    pause_func_t pause_func;
+  };
+
+  void init ()
+  {
+    memset (this, 0, sizeof (*this));
+
+    features.init ();
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+    {
+      lookups[table_index].init ();
+      stages[table_index].init ();
+    }
+  }
+  void fini ()
+  {
+    features.fini ();
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+    {
+      lookups[table_index].fini ();
+      stages[table_index].fini ();
+    }
+  }
+
+  hb_mask_t get_global_mask () const { return global_mask; }
+
+  hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = nullptr) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    if (shift) *shift = map ? map->shift : 0;
+    return map ? map->mask : 0;
+  }
+
+  bool needs_fallback (hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->needs_fallback : false;
+  }
+
+  hb_mask_t get_1_mask (hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->_1_mask : 0;
+  }
+
+  unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX;
+  }
+
+  unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const
+  {
+    const feature_map_t *map = features.bsearch (feature_tag);
+    return map ? map->stage[table_index] : (unsigned int) -1;
+  }
+
+  void get_stage_lookups (unsigned int table_index, unsigned int stage,
+                          const struct lookup_map_t **plookups, unsigned int *lookup_count) const
+  {
+    if (unlikely (stage == (unsigned int) -1)) {
+      *plookups = nullptr;
+      *lookup_count = 0;
+      return;
+    }
+    assert (stage <= stages[table_index].length);
+    unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
+    unsigned int end   = stage < stages[table_index].length ? stages[table_index][stage].last_lookup : lookups[table_index].length;
+    *plookups = end == start ? nullptr : &lookups[table_index][start];
+    *lookup_count = end - start;
+  }
+
+  HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
+  template <typename Proxy>
+  HB_INTERNAL inline void apply (const Proxy &proxy,
+                                 const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const;
+
+  public:
+  hb_tag_t chosen_script[2];
+  bool found_script[2];
+
+  private:
+
+  hb_mask_t global_mask;
+
+  hb_vector_t<feature_map_t> features;
+  hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */
+  hb_vector_t<stage_map_t> stages[2]; /* GSUB/GPOS */
+};
+
+enum hb_ot_map_feature_flags_t
+{
+  F_NONE                = 0x0000u,
+  F_GLOBAL              = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
+  F_HAS_FALLBACK        = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */
+  F_MANUAL_ZWNJ         = 0x0004u, /* Don't skip over ZWNJ when matching **context**. */
+  F_MANUAL_ZWJ          = 0x0008u, /* Don't skip over ZWJ when matching **input**. */
+  F_MANUAL_JOINERS      = F_MANUAL_ZWNJ | F_MANUAL_ZWJ,
+  F_GLOBAL_MANUAL_JOINERS= F_GLOBAL | F_MANUAL_JOINERS,
+  F_GLOBAL_HAS_FALLBACK = F_GLOBAL | F_HAS_FALLBACK,
+  F_GLOBAL_SEARCH       = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */
+  F_RANDOM              = 0x0020u  /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+};
+HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
+
+
+struct hb_ot_map_feature_t
+{
+  hb_tag_t tag;
+  hb_ot_map_feature_flags_t flags;
+};
+
+struct hb_ot_shape_plan_key_t;
+
+struct hb_ot_map_builder_t
+{
+  public:
+
+  HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
+                                   const hb_segment_properties_t *props_);
+
+  HB_INTERNAL ~hb_ot_map_builder_t ();
+
+  HB_INTERNAL void add_feature (hb_tag_t tag,
+                                hb_ot_map_feature_flags_t flags=F_NONE,
+                                unsigned int value=1);
+
+  void add_feature (const hb_ot_map_feature_t &feat)
+  { add_feature (feat.tag, feat.flags); }
+
+  void enable_feature (hb_tag_t tag,
+                              hb_ot_map_feature_flags_t flags=F_NONE,
+                              unsigned int value=1)
+  { add_feature (tag, F_GLOBAL | flags, value); }
+
+  void disable_feature (hb_tag_t tag)
+  { add_feature (tag, F_GLOBAL, 0); }
+
+  void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func)
+  { add_pause (0, pause_func); }
+  void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func)
+  { add_pause (1, pause_func); }
+
+  HB_INTERNAL void compile (hb_ot_map_t                  &m,
+                            const hb_ot_shape_plan_key_t &key);
+
+  private:
+
+  HB_INTERNAL void add_lookups (hb_ot_map_t  &m,
+                                unsigned int  table_index,
+                                unsigned int  feature_index,
+                                unsigned int  variations_index,
+                                hb_mask_t     mask,
+                                bool          auto_zwnj = true,
+                                bool          auto_zwj = true,
+                                bool          random = false);
+
+  struct feature_info_t {
+    hb_tag_t tag;
+    unsigned int seq; /* sequence#, used for stable sorting only */
+    unsigned int max_value;
+    hb_ot_map_feature_flags_t flags;
+    unsigned int default_value; /* for non-global features, what should the unset glyphs take */
+    unsigned int stage[2]; /* GSUB/GPOS */
+
+    static int cmp (const void *pa, const void *pb)
+    {
+      const feature_info_t *a = (const feature_info_t *) pa;
+      const feature_info_t *b = (const feature_info_t *) pb;
+      return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
+             (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
+    }
+  };
+
+  struct stage_info_t {
+    unsigned int index;
+    hb_ot_map_t::pause_func_t pause_func;
+  };
+
+  HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func);
+
+  public:
+
+  hb_face_t *face;
+  hb_segment_properties_t props;
+
+  hb_tag_t chosen_script[2];
+  bool found_script[2];
+  unsigned int script_index[2], language_index[2];
+
+  private:
+
+  unsigned int current_stage[2]; /* GSUB/GPOS */
+  hb_vector_t<feature_info_t> feature_infos;
+  hb_vector_t<stage_info_t> stages[2]; /* GSUB/GPOS */
+};
+
+
+
+#endif /* HB_OT_MAP_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-math-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,718 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#ifndef HB_OT_MATH_TABLE_HH
+#define HB_OT_MATH_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-math.h"
+
+namespace OT {
+
+
+struct MathValueRecord
+{
+  hb_position_t get_x_value (hb_font_t *font, const void *base) const
+  { return font->em_scale_x (value) + (base+deviceTable).get_x_delta (font); }
+  hb_position_t get_y_value (hb_font_t *font, const void *base) const
+  { return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && deviceTable.sanitize (c, base));
+  }
+
+  protected:
+  HBINT16                       value;          /* The X or Y value in design units */
+  OffsetTo<Device>      deviceTable;    /* Offset to the device table - from the
+                                         * beginning of parent table.  May be NULL.
+                                         * Suggested format for device table is 1. */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct MathConstants
+{
+  bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+
+    unsigned int count = ARRAY_LENGTH (mathValueRecords);
+    for (unsigned int i = 0; i < count; i++)
+      if (!mathValueRecords[i].sanitize (c, this))
+        return_trace (false);
+
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && sanitize_math_value_records (c));
+  }
+
+  hb_position_t get_value (hb_ot_math_constant_t constant,
+                                  hb_font_t *font) const
+  {
+    switch (constant) {
+
+    case HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN:
+    case HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN:
+      return percentScaleDown[constant - HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN];
+
+    case HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT:
+    case HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT:
+      return font->em_scale_y (minHeight[constant - HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT]);
+
+    case HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE:
+    case HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE:
+    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP:
+    case HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT:
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_x_value (font, this);
+
+    case HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT:
+    case HB_OT_MATH_CONSTANT_AXIS_HEIGHT:
+    case HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN:
+    case HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_MATH_LEADING:
+    case HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER:
+    case HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER:
+    case HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_STACK_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN:
+    case HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN:
+    case HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX:
+    case HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP:
+    case HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS:
+    case HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP:
+    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN:
+    case HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN:
+      return mathValueRecords[constant - HB_OT_MATH_CONSTANT_MATH_LEADING].get_y_value (font, this);
+
+    case HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT:
+      return radicalDegreeBottomRaisePercent;
+
+    default:
+      return 0;
+    }
+  }
+
+  protected:
+  HBINT16 percentScaleDown[2];
+  HBUINT16 minHeight[2];
+  MathValueRecord mathValueRecords[51];
+  HBINT16 radicalDegreeBottomRaisePercent;
+
+  public:
+  DEFINE_SIZE_STATIC (214);
+};
+
+struct MathItalicsCorrectionInfo
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  coverage.sanitize (c, this) &&
+                  italicsCorrection.sanitize (c, this));
+  }
+
+  hb_position_t get_value (hb_codepoint_t glyph,
+                           hb_font_t *font) const
+  {
+    unsigned int index = (this+coverage).get_coverage (glyph);
+    return italicsCorrection[index].get_x_value (font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>       coverage;            /* Offset to Coverage table -
+                                                 * from the beginning of
+                                                 * MathItalicsCorrectionInfo
+                                                 * table. */
+  ArrayOf<MathValueRecord> italicsCorrection;   /* Array of MathValueRecords
+                                                 * defining italics correction
+                                                 * values for each
+                                                 * covered glyph. */
+
+  public:
+  DEFINE_SIZE_ARRAY (4, italicsCorrection);
+};
+
+struct MathTopAccentAttachment
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  topAccentCoverage.sanitize (c, this) &&
+                  topAccentAttachment.sanitize (c, this));
+  }
+
+  hb_position_t get_value (hb_codepoint_t glyph,
+                           hb_font_t *font) const
+  {
+    unsigned int index = (this+topAccentCoverage).get_coverage (glyph);
+    if (index == NOT_COVERED)
+      return font->get_glyph_h_advance (glyph) / 2;
+    return topAccentAttachment[index].get_x_value (font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>       topAccentCoverage;   /* Offset to Coverage table -
+                                                 * from the beginning of
+                                                 * MathTopAccentAttachment
+                                                 * table. */
+  ArrayOf<MathValueRecord> topAccentAttachment; /* Array of MathValueRecords
+                                                 * defining top accent
+                                                 * attachment points for each
+                                                 * covered glyph. */
+
+  public:
+  DEFINE_SIZE_ARRAY (2 + 2, topAccentAttachment);
+};
+
+struct MathKern
+{
+  bool sanitize_math_value_records (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count = 2 * heightCount + 1;
+    for (unsigned int i = 0; i < count; i++)
+      if (!mathValueRecordsZ.arrayZ[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  c->check_array (mathValueRecordsZ.arrayZ, 2 * heightCount + 1) &&
+                  sanitize_math_value_records (c));
+  }
+
+  hb_position_t get_value (hb_position_t correction_height, hb_font_t *font) const
+  {
+    const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ;
+    const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
+    int sign = font->y_scale < 0 ? -1 : +1;
+
+    /* The description of the MathKern table is a ambiguous, but interpreting
+     * "between the two heights found at those indexes" for 0 < i < len as
+     *
+     *   correctionHeight[i-1] < correction_height <= correctionHeight[i]
+     *
+     * makes the result consistent with the limit cases and we can just use the
+     * binary search algorithm of std::upper_bound:
+     */
+    unsigned int i = 0;
+    unsigned int count = heightCount;
+    while (count > 0)
+    {
+      unsigned int half = count / 2;
+      hb_position_t height = correctionHeight[i + half].get_y_value (font, this);
+      if (sign * height < sign * correction_height)
+      {
+        i += half + 1;
+        count -= half + 1;
+      } else
+        count = half;
+    }
+    return kernValue[i].get_x_value (font, this);
+  }
+
+  protected:
+  HBUINT16      heightCount;
+  UnsizedArrayOf<MathValueRecord>
+                mathValueRecordsZ;      /* Array of correction heights at
+                                         * which the kern value changes.
+                                         * Sorted by the height value in
+                                         * design units (heightCount entries),
+                                         * Followed by:
+                                         * Array of kern values corresponding
+                                         * to heights. (heightCount+1 entries).
+                                         */
+
+  public:
+  DEFINE_SIZE_ARRAY (2, mathValueRecordsZ);
+};
+
+struct MathKernInfoRecord
+{
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+
+    unsigned int count = ARRAY_LENGTH (mathKern);
+    for (unsigned int i = 0; i < count; i++)
+      if (unlikely (!mathKern[i].sanitize (c, base)))
+        return_trace (false);
+
+    return_trace (true);
+  }
+
+  hb_position_t get_kerning (hb_ot_math_kern_t kern,
+                             hb_position_t correction_height,
+                             hb_font_t *font,
+                             const void *base) const
+  {
+    unsigned int idx = kern;
+    if (unlikely (idx >= ARRAY_LENGTH (mathKern))) return 0;
+    return (base+mathKern[idx]).get_value (correction_height, font);
+  }
+
+  protected:
+  /* Offset to MathKern table for each corner -
+   * from the beginning of MathKernInfo table.  May be NULL. */
+  OffsetTo<MathKern> mathKern[4];
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct MathKernInfo
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  mathKernCoverage.sanitize (c, this) &&
+                  mathKernInfoRecords.sanitize (c, this));
+  }
+
+  hb_position_t get_kerning (hb_codepoint_t glyph,
+                             hb_ot_math_kern_t kern,
+                             hb_position_t correction_height,
+                             hb_font_t *font) const
+  {
+    unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
+    return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
+  }
+
+  protected:
+  OffsetTo<Coverage>            mathKernCoverage;    /* Offset to Coverage table -
+                                                      * from the beginning of the
+                                                      * MathKernInfo table. */
+  ArrayOf<MathKernInfoRecord>   mathKernInfoRecords; /* Array of
+                                                      * MathKernInfoRecords,
+                                                      * per-glyph information for
+                                                      * mathematical positioning
+                                                      * of subscripts and
+                                                      * superscripts. */
+
+  public:
+  DEFINE_SIZE_ARRAY (4, mathKernInfoRecords);
+};
+
+struct MathGlyphInfo
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  mathItalicsCorrectionInfo.sanitize (c, this) &&
+                  mathTopAccentAttachment.sanitize (c, this) &&
+                  extendedShapeCoverage.sanitize (c, this) &&
+                  mathKernInfo.sanitize (c, this));
+  }
+
+  hb_position_t
+  get_italics_correction (hb_codepoint_t  glyph, hb_font_t *font) const
+  { return (this+mathItalicsCorrectionInfo).get_value (glyph, font); }
+
+  hb_position_t
+  get_top_accent_attachment (hb_codepoint_t  glyph, hb_font_t *font) const
+  { return (this+mathTopAccentAttachment).get_value (glyph, font); }
+
+  bool is_extended_shape (hb_codepoint_t glyph) const
+  { return (this+extendedShapeCoverage).get_coverage (glyph) != NOT_COVERED; }
+
+  hb_position_t get_kerning (hb_codepoint_t glyph,
+                             hb_ot_math_kern_t kern,
+                             hb_position_t correction_height,
+                             hb_font_t *font) const
+  { return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
+
+  protected:
+  /* Offset to MathItalicsCorrectionInfo table -
+   * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathItalicsCorrectionInfo> mathItalicsCorrectionInfo;
+
+  /* Offset to MathTopAccentAttachment table -
+   * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathTopAccentAttachment> mathTopAccentAttachment;
+
+  /* Offset to coverage table for Extended Shape glyphs -
+   * from the beginning of MathGlyphInfo table. When the left or right glyph of
+   * a box is an extended shape variant, the (ink) box (and not the default
+   * position defined by values in MathConstants table) should be used for
+   * vertical positioning purposes.  May be NULL.. */
+  OffsetTo<Coverage> extendedShapeCoverage;
+
+   /* Offset to MathKernInfo table -
+    * from the beginning of MathGlyphInfo table. */
+  OffsetTo<MathKernInfo> mathKernInfo;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct MathGlyphVariantRecord
+{
+  friend struct MathGlyphConstruction;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  protected:
+  GlyphID variantGlyph;       /* Glyph ID for the variant. */
+  HBUINT16  advanceMeasurement; /* Advance width/height, in design units, of the
+                                 * variant, in the direction of requested
+                                 * glyph extension. */
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct PartFlags : HBUINT16
+{
+  enum Flags {
+    Extender    = 0x0001u, /* If set, the part can be skipped or repeated. */
+
+    Defined     = 0x0001u, /* All defined flags. */
+  };
+
+  public:
+  DEFINE_SIZE_STATIC (2);
+};
+
+struct MathGlyphPartRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  void extract (hb_ot_math_glyph_part_t &out,
+                int scale,
+                hb_font_t *font) const
+  {
+    out.glyph                   = glyph;
+
+    out.start_connector_length  = font->em_scale (startConnectorLength, scale);
+    out.end_connector_length    = font->em_scale (endConnectorLength, scale);
+    out.full_advance            = font->em_scale (fullAdvance, scale);
+
+    static_assert ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
+                   (unsigned int) PartFlags::Extender, "");
+
+    out.flags = (hb_ot_math_glyph_part_flags_t)
+                (unsigned int)
+                (partFlags & PartFlags::Defined);
+  }
+
+  protected:
+  GlyphID   glyph;                /* Glyph ID for the part. */
+  HBUINT16    startConnectorLength; /* Advance width/ height of the straight bar
+                                   * connector material, in design units, is at
+                                   * the beginning of the glyph, in the
+                                   * direction of the extension. */
+  HBUINT16    endConnectorLength;   /* Advance width/ height of the straight bar
+                                   * connector material, in design units, is at
+                                   * the end of the glyph, in the direction of
+                                   * the extension. */
+  HBUINT16    fullAdvance;        /* Full advance width/height for this part,
+                                   * in the direction of the extension.
+                                   * In design units. */
+  PartFlags partFlags;            /* Part qualifiers. */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct MathGlyphAssembly
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  italicsCorrection.sanitize (c, this) &&
+                  partRecords.sanitize (c));
+  }
+
+  unsigned int get_parts (hb_direction_t direction,
+                          hb_font_t *font,
+                          unsigned int start_offset,
+                          unsigned int *parts_count, /* IN/OUT */
+                          hb_ot_math_glyph_part_t *parts /* OUT */,
+                          hb_position_t *italics_correction /* OUT */) const
+  {
+    if (parts_count)
+    {
+      int scale = font->dir_scale (direction);
+      hb_array_t<const MathGlyphPartRecord> arr = partRecords.sub_array (start_offset, parts_count);
+      unsigned int count = arr.length;
+      for (unsigned int i = 0; i < count; i++)
+        arr[i].extract (parts[i], scale, font);
+    }
+
+    if (italics_correction)
+      *italics_correction = italicsCorrection.get_x_value (font, this);
+
+    return partRecords.len;
+  }
+
+  protected:
+  MathValueRecord          italicsCorrection; /* Italics correction of this
+                                               * MathGlyphAssembly. Should not
+                                               * depend on the assembly size. */
+  ArrayOf<MathGlyphPartRecord> partRecords;   /* Array of part records, from
+                                               * left to right and bottom to
+                                               * top. */
+
+  public:
+  DEFINE_SIZE_ARRAY (6, partRecords);
+};
+
+struct MathGlyphConstruction
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  glyphAssembly.sanitize (c, this) &&
+                  mathGlyphVariantRecord.sanitize (c));
+  }
+
+  const MathGlyphAssembly &get_assembly () const { return this+glyphAssembly; }
+
+  unsigned int get_variants (hb_direction_t direction,
+                             hb_font_t *font,
+                             unsigned int start_offset,
+                             unsigned int *variants_count, /* IN/OUT */
+                             hb_ot_math_glyph_variant_t *variants /* OUT */) const
+  {
+    if (variants_count)
+    {
+      int scale = font->dir_scale (direction);
+      hb_array_t<const MathGlyphVariantRecord> arr = mathGlyphVariantRecord.sub_array (start_offset, variants_count);
+      unsigned int count = arr.length;
+      for (unsigned int i = 0; i < count; i++)
+      {
+        variants[i].glyph = arr[i].variantGlyph;
+        variants[i].advance = font->em_scale (arr[i].advanceMeasurement, scale);
+      }
+    }
+    return mathGlyphVariantRecord.len;
+  }
+
+  protected:
+  /* Offset to MathGlyphAssembly table for this shape - from the beginning of
+     MathGlyphConstruction table.  May be NULL. */
+  OffsetTo<MathGlyphAssembly>     glyphAssembly;
+
+  /* MathGlyphVariantRecords for alternative variants of the glyphs. */
+  ArrayOf<MathGlyphVariantRecord> mathGlyphVariantRecord;
+
+  public:
+  DEFINE_SIZE_ARRAY (4, mathGlyphVariantRecord);
+};
+
+struct MathVariants
+{
+  bool sanitize_offsets (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    unsigned int count = vertGlyphCount + horizGlyphCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (!glyphConstruction.arrayZ[i].sanitize (c, this)) return_trace (false);
+    return_trace (true);
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  vertGlyphCoverage.sanitize (c, this) &&
+                  horizGlyphCoverage.sanitize (c, this) &&
+                  c->check_array (glyphConstruction.arrayZ, vertGlyphCount + horizGlyphCount) &&
+                  sanitize_offsets (c));
+  }
+
+  hb_position_t get_min_connector_overlap (hb_direction_t direction,
+                                                  hb_font_t *font) const
+  { return font->em_scale_dir (minConnectorOverlap, direction); }
+
+  unsigned int get_glyph_variants (hb_codepoint_t glyph,
+                                   hb_direction_t direction,
+                                   hb_font_t *font,
+                                   unsigned int start_offset,
+                                   unsigned int *variants_count, /* IN/OUT */
+                                   hb_ot_math_glyph_variant_t *variants /* OUT */) const
+  { return get_glyph_construction (glyph, direction, font)
+           .get_variants (direction, font, start_offset, variants_count, variants); }
+
+  unsigned int get_glyph_parts (hb_codepoint_t glyph,
+                                       hb_direction_t direction,
+                                       hb_font_t *font,
+                                       unsigned int start_offset,
+                                       unsigned int *parts_count, /* IN/OUT */
+                                       hb_ot_math_glyph_part_t *parts /* OUT */,
+                                       hb_position_t *italics_correction /* OUT */) const
+  { return get_glyph_construction (glyph, direction, font)
+           .get_assembly ()
+           .get_parts (direction, font,
+                       start_offset, parts_count, parts,
+                       italics_correction); }
+
+  private:
+  const MathGlyphConstruction &
+  get_glyph_construction (hb_codepoint_t glyph,
+                          hb_direction_t direction,
+                          hb_font_t *font HB_UNUSED) const
+  {
+    bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
+    unsigned int count = vertical ? vertGlyphCount : horizGlyphCount;
+    const OffsetTo<Coverage> &coverage = vertical ? vertGlyphCoverage
+                                                  : horizGlyphCoverage;
+
+    unsigned int index = (this+coverage).get_coverage (glyph);
+    if (unlikely (index >= count)) return Null (MathGlyphConstruction);
+
+    if (!vertical)
+      index += vertGlyphCount;
+
+    return this+glyphConstruction[index];
+  }
+
+  protected:
+  HBUINT16           minConnectorOverlap; /* Minimum overlap of connecting
+                                           * glyphs during glyph construction,
+                                           * in design units. */
+  OffsetTo<Coverage> vertGlyphCoverage;   /* Offset to Coverage table -
+                                           * from the beginning of MathVariants
+                                           * table. */
+  OffsetTo<Coverage> horizGlyphCoverage;  /* Offset to Coverage table -
+                                           * from the beginning of MathVariants
+                                           * table. */
+  HBUINT16           vertGlyphCount;      /* Number of glyphs for which
+                                           * information is provided for
+                                           * vertically growing variants. */
+  HBUINT16           horizGlyphCount;     /* Number of glyphs for which
+                                           * information is provided for
+                                           * horizontally growing variants. */
+
+  /* Array of offsets to MathGlyphConstruction tables - from the beginning of
+     the MathVariants table, for shapes growing in vertical/horizontal
+     direction. */
+  UnsizedArrayOf<OffsetTo<MathGlyphConstruction> >
+                        glyphConstruction;
+
+  public:
+  DEFINE_SIZE_ARRAY (10, glyphConstruction);
+};
+
+
+/*
+ * MATH -- Mathematical typesetting
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/math
+ */
+
+struct MATH
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_MATH;
+
+  bool has_data () const { return version.to_int (); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+                  likely (version.major == 1) &&
+                  mathConstants.sanitize (c, this) &&
+                  mathGlyphInfo.sanitize (c, this) &&
+                  mathVariants.sanitize (c, this));
+  }
+
+  hb_position_t get_constant (hb_ot_math_constant_t  constant,
+                                     hb_font_t             *font) const
+  { return (this+mathConstants).get_value (constant, font); }
+
+  const MathGlyphInfo &get_glyph_info () const { return this+mathGlyphInfo; }
+
+  const MathVariants &get_variants () const    { return this+mathVariants; }
+
+  protected:
+  FixedVersion<>version;                /* Version of the MATH table
+                                         * initially set to 0x00010000u */
+  OffsetTo<MathConstants> mathConstants;/* MathConstants table */
+  OffsetTo<MathGlyphInfo> mathGlyphInfo;/* MathGlyphInfo table */
+  OffsetTo<MathVariants>  mathVariants; /* MathVariants table */
+
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_MATH_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-math.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,253 @@
+/*
+ * Copyright © 2016  Igalia S.L.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Igalia Author(s): Frédéric Wang
+ */
+
+#include "hb-open-type.hh"
+
+#include "hb-ot-face.hh"
+#include "hb-ot-math-table.hh"
+
+
+/**
+ * SECTION:hb-ot-math
+ * @title: hb-ot-math
+ * @short_description: OpenType Math information
+ * @include: hb-ot.h
+ *
+ * Functions for fetching mathematics layout data from OpenType fonts.
+ **/
+
+
+/*
+ * OT::MATH
+ */
+
+/**
+ * hb_ot_math_has_data:
+ * @face: #hb_face_t to test
+ *
+ * This function allows to verify the presence of an OpenType MATH table on the
+ * face.
+ *
+ * Return value: true if face has a MATH table, false otherwise
+ *
+ * Since: 1.3.3
+ **/
+hb_bool_t
+hb_ot_math_has_data (hb_face_t *face)
+{
+  return face->table.MATH->has_data ();
+}
+
+/**
+ * hb_ot_math_get_constant:
+ * @font: #hb_font_t from which to retrieve the value
+ * @constant: #hb_ot_math_constant_t the constant to retrieve
+ *
+ * This function returns the requested math constants as a #hb_position_t.
+ * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
+ * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
+ * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
+ * actually an integer between 0 and 100 representing that percentage.
+ *
+ * Return value: the requested constant or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_constant (hb_font_t *font,
+                         hb_ot_math_constant_t constant)
+{
+  return font->face->table.MATH->get_constant(constant, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_italics_correction:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the italics correction of the glyph or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
+                                         hb_codepoint_t glyph)
+{
+  return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_top_accent_attachment:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ *
+ * Return value: the top accent attachment of the glyph or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
+                                            hb_codepoint_t glyph)
+{
+  return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font);
+}
+
+/**
+ * hb_ot_math_is_glyph_extended_shape:
+ * @face: a #hb_face_t to test
+ * @glyph: a glyph index to test
+ *
+ * Return value: true if the glyph is an extended shape, false otherwise
+ *
+ * Since: 1.3.3
+ **/
+hb_bool_t
+hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
+                                    hb_codepoint_t glyph)
+{
+  return face->table.MATH->get_glyph_info().is_extended_shape (glyph);
+}
+
+/**
+ * hb_ot_math_get_glyph_kerning:
+ * @font: #hb_font_t from which to retrieve the value
+ * @glyph: glyph index from which to retrieve the value
+ * @kern: the #hb_ot_math_kern_t from which to retrieve the value
+ * @correction_height: the correction height to use to determine the kerning.
+ *
+ * This function tries to retrieve the MathKern table for the specified font,
+ * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
+ * MathKern table to find one value that is greater or equal to specified
+ * correction_height. If one is found the corresponding value from the list of
+ * kerns is returned and otherwise the last kern value is returned.
+ *
+ * Return value: requested kerning or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_glyph_kerning (hb_font_t *font,
+                              hb_codepoint_t glyph,
+                              hb_ot_math_kern_t kern,
+                              hb_position_t correction_height)
+{
+  return font->face->table.MATH->get_glyph_info().get_kerning (glyph,
+                                                               kern,
+                                                               correction_height,
+                                                               font);
+}
+
+/**
+ * hb_ot_math_get_glyph_variants:
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first variant to retrieve
+ * @variants_count: maximum number of variants to retrieve after start_offset
+ * (IN) and actual number of variants retrieved (OUT)
+ * @variants: array of size at least @variants_count to store the result
+ *
+ * This function tries to retrieve the MathGlyphConstruction for the specified
+ * font, glyph and direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
+ * of size variants as an array of hb_ot_math_glyph_variant_t structs.
+ *
+ * Return value: the total number of size variants available or 0
+ *
+ * Since: 1.3.3
+ **/
+unsigned int
+hb_ot_math_get_glyph_variants (hb_font_t *font,
+                               hb_codepoint_t glyph,
+                               hb_direction_t direction,
+                               unsigned int start_offset,
+                               unsigned int *variants_count, /* IN/OUT */
+                               hb_ot_math_glyph_variant_t *variants /* OUT */)
+{
+  return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font,
+                                                                    start_offset,
+                                                                    variants_count,
+                                                                    variants);
+}
+
+/**
+ * hb_ot_math_get_min_connector_overlap:
+ * @font: #hb_font_t from which to retrieve the value
+ * @direction: direction of the stretching
+ *
+ * This function tries to retrieve the MathVariants table for the specified
+ * font and returns the minimum overlap of connecting glyphs to draw a glyph
+ * assembly in the specified direction. Note that only the value of
+ * #HB_DIRECTION_IS_HORIZONTAL is considered.
+ *
+ * Return value: requested min connector overlap or 0
+ *
+ * Since: 1.3.3
+ **/
+hb_position_t
+hb_ot_math_get_min_connector_overlap (hb_font_t *font,
+                                      hb_direction_t direction)
+{
+  return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font);
+}
+
+/**
+ * hb_ot_math_get_glyph_assembly:
+ * @font: #hb_font_t from which to retrieve the values
+ * @glyph: index of the glyph to stretch
+ * @direction: direction of the stretching
+ * @start_offset: offset of the first glyph part to retrieve
+ * @parts_count: maximum number of glyph parts to retrieve after start_offset
+ * (IN) and actual number of parts retrieved (OUT)
+ * @parts: array of size at least @parts_count to store the result
+ * @italics_correction: italic correction of the glyph assembly
+ *
+ * This function tries to retrieve the GlyphAssembly for the specified font,
+ * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
+ * is considered. It provides the information necessary to draw the glyph
+ * assembly as an array of #hb_ot_math_glyph_part_t.
+ *
+ * Return value: the total number of parts in the glyph assembly
+ *
+ * Since: 1.3.3
+ **/
+unsigned int
+hb_ot_math_get_glyph_assembly (hb_font_t *font,
+                               hb_codepoint_t glyph,
+                               hb_direction_t direction,
+                               unsigned int start_offset,
+                               unsigned int *parts_count, /* IN/OUT */
+                               hb_ot_math_glyph_part_t *parts, /* OUT */
+                               hb_position_t *italics_correction /* OUT */)
+{
+  return font->face->table.MATH->get_variants().get_glyph_parts (glyph,
+                                                                 direction,
+                                                                 font,
+                                                                 start_offset,
+                                                                 parts_count,
+                                                                 parts,
+                                                                 italics_correction);
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-maxp-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-maxp-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,8 +27,7 @@
 #ifndef HB_OT_MAXP_TABLE_HH
 #define HB_OT_MAXP_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
 
 namespace OT {
 
@@ -42,7 +41,7 @@
 
 struct maxpV1Tail
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -72,19 +71,16 @@
 
 struct maxp
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_maxp;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_maxp;
 
-  inline unsigned int get_num_glyphs (void) const
-  {
-    return numGlyphs;
-  }
+  unsigned int get_num_glyphs () const { return numGlyphs; }
 
-  inline void set_num_glyphs (unsigned int count)
+  void set_num_glyphs (unsigned int count)
   {
     numGlyphs.set (count);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this)))
@@ -93,23 +89,23 @@
     if (version.major == 1)
     {
       const maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*this);
-      return v1.sanitize (c);
+      return_trace (v1.sanitize (c));
     }
     return_trace (likely (version.major == 0 && version.minor == 0x5000u));
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
-    hb_blob_t *maxp_blob = OT::Sanitizer<OT::maxp>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_maxp));
+    hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table<maxp> (plan->source);
     hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
     hb_blob_destroy (maxp_blob);
 
     if (unlikely (!maxp_prime_blob)) {
       return false;
     }
-    OT::maxp *maxp_prime = (OT::maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
+    maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
 
-    maxp_prime->set_num_glyphs (plan->glyphs.len);
+    maxp_prime->set_num_glyphs (plan->glyphs.length);
     if (plan->drop_hints)
       drop_hint_fields (plan, maxp_prime);
 
@@ -118,7 +114,7 @@
     return result;
   }
 
-  static inline void drop_hint_fields (hb_subset_plan_t *plan, OT::maxp *maxp_prime)
+  static void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime)
   {
     if (maxp_prime->version.major == 1)
     {
@@ -137,7 +133,7 @@
   FixedVersion<>version;                /* Version of the maxp table (0.5 or 1.0),
                                          * 0x00005000u or 0x00010000u. */
   HBUINT16      numGlyphs;              /* The number of glyphs in the font. */
-/*maxpV1Tail v1Tail[VAR]; */
+/*maxpV1Tail    v1Tail[VAR]; */
   public:
   DEFINE_SIZE_STATIC (6);
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-language.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,457 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-ot-name-language.hh"
+
+/* Following two tables were generated by joining FreeType, FontConfig,
+ * and OpenType specification language lists, then filled in missing
+ * entries using:
+ * https://docs.microsoft.com/en-us/windows/desktop/intl/language-identifier-constants-and-strings
+ */
+
+struct hb_ot_language_map_t
+{
+  static int cmp (const void *key, const void *item)
+  {
+    unsigned int a = * (unsigned int *) key;
+    unsigned int b = ((const hb_ot_language_map_t *) item)->code;
+    return a < b ? -1 : a > b ? +1 : 0;
+  }
+
+  uint16_t      code;
+  char          lang[6];
+};
+
+static const hb_ot_language_map_t
+hb_ms_language_map[] =
+{
+  {0x0001,      "ar"},  /* ??? */
+  {0x0004,      "zh"},  /* ??? */
+  {0x0009,      "en"},  /* ??? */
+  {0x0401,      "ar"},  /* Arabic (Saudi Arabia) */
+  {0x0402,      "bg"},  /* Bulgarian (Bulgaria) */
+  {0x0403,      "ca"},  /* Catalan (Catalan) */
+  {0x0404,      "zh-tw"},       /* Chinese (Taiwan) */
+  {0x0405,      "cs"},  /* Czech (Czech Republic) */
+  {0x0406,      "da"},  /* Danish (Denmark) */
+  {0x0407,      "de"},  /* German (Germany) */
+  {0x0408,      "el"},  /* Greek (Greece) */
+  {0x0409,      "en"},  /* English (United States) */
+  {0x040A,      "es"},  /* Spanish (Traditional Sort) (Spain) */
+  {0x040B,      "fi"},  /* Finnish (Finland) */
+  {0x040C,      "fr"},  /* French (France) */
+  {0x040D,      "he"},  /* Hebrew (Israel) */
+  {0x040E,      "hu"},  /* Hungarian (Hungary) */
+  {0x040F,      "is"},  /* Icelandic (Iceland) */
+  {0x0410,      "it"},  /* Italian (Italy) */
+  {0x0411,      "ja"},  /* Japanese (Japan) */
+  {0x0412,      "ko"},  /* Korean (Korea) */
+  {0x0413,      "nl"},  /* Dutch (Netherlands) */
+  {0x0414,      "no"},  /* Norwegian (Bokmal) (Norway) */
+  {0x0415,      "pl"},  /* Polish (Poland) */
+  {0x0416,      "pt"},  /* Portuguese (Brazil) */
+  {0x0417,      "rm"},  /* Romansh (Switzerland) */
+  {0x0418,      "ro"},  /* Romanian (Romania) */
+  {0x0419,      "ru"},  /* Russian (Russia) */
+  {0x041A,      "hr"},  /* Croatian (Croatia) */
+  {0x041B,      "sk"},  /* Slovak (Slovakia) */
+  {0x041C,      "sq"},  /* Albanian (Albania) */
+  {0x041D,      "sv"},  /* Swedish (Sweden) */
+  {0x041E,      "th"},  /* Thai (Thailand) */
+  {0x041F,      "tr"},  /* Turkish (Turkey) */
+  {0x0420,      "ur"},  /* Urdu (Islamic Republic of Pakistan) */
+  {0x0421,      "id"},  /* Indonesian (Indonesia) */
+  {0x0422,      "uk"},  /* Ukrainian (Ukraine) */
+  {0x0423,      "be"},  /* Belarusian (Belarus) */
+  {0x0424,      "sl"},  /* Slovenian (Slovenia) */
+  {0x0425,      "et"},  /* Estonian (Estonia) */
+  {0x0426,      "lv"},  /* Latvian (Latvia) */
+  {0x0427,      "lt"},  /* Lithuanian (Lithuania) */
+  {0x0428,      "tg"},  /* Tajik (Cyrillic) (Tajikistan) */
+  {0x0429,      "fa"},  /* Persian (Iran) */
+  {0x042A,      "vi"},  /* Vietnamese (Vietnam) */
+  {0x042B,      "hy"},  /* Armenian (Armenia) */
+  {0x042C,      "az"},  /* Azeri (Latin) (Azerbaijan) */
+  {0x042D,      "eu"},  /* Basque (Basque) */
+  {0x042E,      "hsb"}, /* Upper Sorbian (Germany) */
+  {0x042F,      "mk"},  /* Macedonian (FYROM) (Former Yugoslav Republic of Macedonia) */
+  {0x0430,      "st"},  /* ??? */
+  {0x0431,      "ts"},  /* ??? */
+  {0x0432,      "tn"},  /* Setswana (South Africa) */
+  {0x0433,      "ven"}, /* ??? */
+  {0x0434,      "xh"},  /* isiXhosa (South Africa) */
+  {0x0435,      "zu"},  /* isiZulu (South Africa) */
+  {0x0436,      "af"},  /* Afrikaans (South Africa) */
+  {0x0437,      "ka"},  /* Georgian (Georgia) */
+  {0x0438,      "fo"},  /* Faroese (Faroe Islands) */
+  {0x0439,      "hi"},  /* Hindi (India) */
+  {0x043A,      "mt"},  /* Maltese (Malta) */
+  {0x043B,      "se"},  /* Sami (Northern) (Norway) */
+  {0x043C,      "ga"},  /* ??? */
+  {0x043D,      "yi"},  /* ??? */
+  {0x043E,      "ms"},  /* Malay (Malaysia) */
+  {0x043F,      "kk"},  /* Kazakh (Kazakhstan) */
+  {0x0440,      "ky"},  /* Kyrgyz (Kyrgyzstan) */
+  {0x0441,      "sw"},  /* Kiswahili (Kenya) */
+  {0x0442,      "tk"},  /* Turkmen (Turkmenistan) */
+  {0x0443,      "uz"},  /* Uzbek (Latin) (Uzbekistan) */
+  {0x0444,      "tt"},  /* Tatar (Russia) */
+  {0x0445,      "bn"},  /* Bengali (India) */
+  {0x0446,      "pa"},  /* Punjabi (India) */
+  {0x0447,      "gu"},  /* Gujarati (India) */
+  {0x0448,      "or"},  /* Odia (formerly Oriya) (India) */
+  {0x0449,      "ta"},  /* Tamil (India) */
+  {0x044A,      "te"},  /* Telugu (India) */
+  {0x044B,      "kn"},  /* Kannada (India) */
+  {0x044C,      "ml"},  /* Malayalam (India) */
+  {0x044D,      "as"},  /* Assamese (India) */
+  {0x044E,      "mr"},  /* Marathi (India) */
+  {0x044F,      "sa"},  /* Sanskrit (India) */
+  {0x0450,      "mn"},  /* Mongolian (Cyrillic) (Mongolia) */
+  {0x0451,      "bo"},  /* Tibetan (PRC) */
+  {0x0452,      "cy"},  /* Welsh (United Kingdom) */
+  {0x0453,      "km"},  /* Khmer (Cambodia) */
+  {0x0454,      "lo"},  /* Lao (Lao P.D.R.) */
+  {0x0455,      "my"},  /* ??? */
+  {0x0456,      "gl"},  /* Galician (Galician) */
+  {0x0457,      "kok"}, /* Konkani (India) */
+  {0x0458,      "mni"}, /* ??? */
+  {0x0459,      "sd"},  /* ??? */
+  {0x045A,      "syr"}, /* Syriac (Syria) */
+  {0x045B,      "si"},  /* Sinhala (Sri Lanka) */
+  {0x045C,      "chr"}, /* ??? */
+  {0x045D,      "iu"},  /* Inuktitut (Canada) */
+  {0x045E,      "am"},  /* Amharic (Ethiopia) */
+  {0x0460,      "ks"},  /* ??? */
+  {0x0461,      "ne"},  /* Nepali (Nepal) */
+  {0x0462,      "fy"},  /* Frisian (Netherlands) */
+  {0x0463,      "ps"},  /* Pashto (Afghanistan) */
+  {0x0464,      "phi"}, /* Filipino (Philippines) */
+  {0x0465,      "div"}, /* Divehi (Maldives) */
+  {0x0468,      "ha"},  /* Hausa (Latin) (Nigeria) */
+  {0x046A,      "yo"},  /* Yoruba (Nigeria) */
+  {0x046B,      "quz"}, /* Quechua (Bolivia) */
+  {0x046C,      "nso"}, /* Sesotho sa Leboa (South Africa) */
+  {0x046D,      "ba"},  /* Bashkir (Russia) */
+  {0x046E,      "lb"},  /* Luxembourgish (Luxembourg) */
+  {0x046F,      "kl"},  /* Greenlandic (Greenland) */
+  {0x0470,      "ibo"}, /* Igbo (Nigeria) */
+  {0x0471,      "kau"}, /* ??? */
+  {0x0472,      "om"},  /* ??? */
+  {0x0473,      "ti"},  /* ??? */
+  {0x0474,      "gn"},  /* ??? */
+  {0x0475,      "haw"}, /* ??? */
+  {0x0476,      "la"},  /* ??? */
+  {0x0477,      "so"},  /* ??? */
+  {0x0478,      "ii"},  /* Yi (PRC) */
+  {0x0479,      "pap"}, /* ??? */
+  {0x047A,      "arn"}, /* Mapudungun (Chile) */
+  {0x047C,      "moh"}, /* Mohawk (Mohawk) */
+  {0x047E,      "br"},  /* Breton (France) */
+  {0x0480,      "ug"},  /* Uighur (PRC) */
+  {0x0481,      "mi"},  /* Maori (New Zealand) */
+  {0x0482,      "oc"},  /* Occitan (France) */
+  {0x0483,      "co"},  /* Corsican (France) */
+  {0x0484,      "gsw"}, /* Alsatian (France) */
+  {0x0485,      "sah"}, /* Yakut (Russia) */
+  {0x0486,      "qut"}, /* K'iche (Guatemala) */
+  {0x0487,      "rw"},  /* Kinyarwanda (Rwanda) */
+  {0x0488,      "wo"},  /* Wolof (Senegal) */
+  {0x048C,      "fa"},  /* Dari (Afghanistan) */
+  {0x0801,      "ar"},  /* Arabic (Iraq) */
+  {0x0804,      "zh-cn"},       /* Chinese (People’s Republic of China) */
+  {0x0807,      "de"},  /* German (Switzerland) */
+  {0x0809,      "en"},  /* English (United Kingdom) */
+  {0x080A,      "es"},  /* Spanish (Mexico) */
+  {0x080C,      "fr"},  /* French (Belgium) */
+  {0x0810,      "it"},  /* Italian (Switzerland) */
+  {0x0812,      "ko"},  /* ??? */
+  {0x0813,      "nl"},  /* Dutch (Belgium) */
+  {0x0814,      "nn"},  /* Norwegian (Nynorsk) (Norway) */
+  {0x0816,      "pt"},  /* Portuguese (Portugal) */
+  {0x0818,      "mo"},  /* ??? */
+  {0x0819,      "ru"},  /* ??? */
+  {0x081A,      "sr"},  /* Serbian (Latin) (Serbia) */
+  {0x081D,      "sv"},  /* Sweden (Finland) */
+  {0x0820,      "ur"},  /* ??? */
+  {0x0827,      "lt"},  /* ??? */
+  {0x082C,      "az"},  /* Azeri (Cyrillic) (Azerbaijan) */
+  {0x082E,      "dsb"}, /* Lower Sorbian (Germany) */
+//{0x083B,      ""},    /* Sami (Northern) (Sweden) */
+  {0x083C,      "gd"},  /* Irish (Ireland) */
+  {0x083E,      "ms"},  /* Malay (Brunei Darussalam) */
+  {0x0843,      "uz"},  /* Uzbek (Cyrillic) (Uzbekistan) */
+  {0x0845,      "bn"},  /* Bengali (Bangladesh) */
+  {0x0846,      "ar"},  /* ??? */
+  {0x0850,      "mn"},  /* Mongolian (Traditional) (People’s Republic of China) */
+  {0x0851,      "dz"},  /* ??? */
+  {0x085D,      "iu"},  /* Inuktitut (Latin) (Canada) */
+  {0x085F,      "tzm"}, /* Tamazight (Latin) (Algeria) */
+  {0x0861,      "ne"},  /* ??? */
+//{0x086B,      ""},    /* Quechua (Ecuador) */
+  {0x0873,      "ti"},  /* ??? */
+  {0x0C01,      "ar"},  /* Arabic (Egypt) */
+  {0x0C04,      "zh-hk"},       /* Chinese (Hong Kong S.A.R.) */
+  {0x0C07,      "de"},  /* German (Austria) */
+  {0x0C09,      "en"},  /* English (Australia) */
+  {0x0C0A,      "es"},  /* Spanish (Modern Sort) (Spain) */
+  {0x0C0C,      "fr"},  /* French (Canada) */
+  {0x0C1A,      "sr"},  /* Serbian (Cyrillic) (Serbia) */
+  {0x0C3B,      "se"},  /* Sami (Northern) (Finland) */
+//{0x0C6B,      ""},    /* Quechua (Peru) */
+  {0x1001,      "ar"},  /* Arabic (Libya) */
+  {0x1004,      "zh-sg"},       /* Chinese (Singapore) */
+  {0x1007,      "de"},  /* German (Luxembourg) */
+  {0x1009,      "en"},  /* English (Canada) */
+  {0x100A,      "es"},  /* Spanish (Guatemala) */
+  {0x100C,      "fr"},  /* French (Switzerland) */
+  {0x101A,      "hr"},  /* Croatian (Latin) (Bosnia and Herzegovina) */
+  {0x103B,      "smj"}, /* Sami (Lule) (Norway) */
+  {0x1401,      "ar"},  /* Arabic (Algeria) */
+//{0x1404,      ""},    /* Chinese (Macao S.A.R.) */
+  {0x1407,      "de"},  /* German (Liechtenstein) */
+  {0x1409,      "en"},  /* English (New Zealand) */
+  {0x140A,      "es"},  /* Spanish (Costa Rica) */
+  {0x140C,      "fr"},  /* French (Luxembourg) */
+  {0x141A,      "bs"},  /* Bosnian (Latin) (Bosnia and Herzegovina) */
+//{0x143B,      ""},    /* Sami (Lule) (Sweden) */
+  {0x1801,      "ar"},  /* Arabic (Morocco) */
+  {0x1809,      "en"},  /* English (Ireland) */
+  {0x180A,      "es"},  /* Spanish (Panama) */
+  {0x180C,      "fr"},  /* French (Principality of Monaco) */
+//{0x181A,      ""},    /* Serbian (Latin) (Bosnia and Herzegovina) */
+  {0x183B,      "sma"}, /* Sami (Southern) (Norway) */
+  {0x1C01,      "ar"},  /* Arabic (Tunisia) */
+  {0x1C09,      "en"},  /* English (South Africa) */
+  {0x1C0A,      "es"},  /* Spanish (Dominican Republic) */
+  {0x1C0C,      "fr"},  /* ??? */
+//{0x1C1A,      ""},    /* Serbian (Cyrillic) (Bosnia and Herzegovina) */
+//{0x1C3B,      ""},    /* Sami (Southern) (Sweden) */
+  {0x2001,      "ar"},  /* Arabic (Oman) */
+  {0x2009,      "en"},  /* English (Jamaica) */
+  {0x200A,      "es"},  /* Spanish (Venezuela) */
+  {0x200C,      "fr"},  /* ??? */
+  {0x201A,      "bs"},  /* Bosnian (Cyrillic) (Bosnia and Herzegovina) */
+  {0x203B,      "sms"}, /* Sami (Skolt) (Finland) */
+  {0x2401,      "ar"},  /* Arabic (Yemen) */
+  {0x2409,      "en"},  /* English (Caribbean) */
+  {0x240A,      "es"},  /* Spanish (Colombia) */
+  {0x240C,      "fr"},  /* ??? */
+  {0x243B,      "smn"}, /* Sami (Inari) (Finland) */
+  {0x2801,      "ar"},  /* Arabic (Syria) */
+  {0x2809,      "en"},  /* English (Belize) */
+  {0x280A,      "es"},  /* Spanish (Peru) */
+  {0x280C,      "fr"},  /* ??? */
+  {0x2C01,      "ar"},  /* Arabic (Jordan) */
+  {0x2C09,      "en"},  /* English (Trinidad and Tobago) */
+  {0x2C0A,      "es"},  /* Spanish (Argentina) */
+  {0x2C0C,      "fr"},  /* ??? */
+  {0x3001,      "ar"},  /* Arabic (Lebanon) */
+  {0x3009,      "en"},  /* English (Zimbabwe) */
+  {0x300A,      "es"},  /* Spanish (Ecuador) */
+  {0x300C,      "fr"},  /* ??? */
+  {0x3401,      "ar"},  /* Arabic (Kuwait) */
+  {0x3409,      "en"},  /* English (Republic of the Philippines) */
+  {0x340A,      "es"},  /* Spanish (Chile) */
+  {0x340C,      "fr"},  /* ??? */
+  {0x3801,      "ar"},  /* Arabic (U.A.E.) */
+  {0x380A,      "es"},  /* Spanish (Uruguay) */
+  {0x380C,      "fr"},  /* ??? */
+  {0x3C01,      "ar"},  /* Arabic (Bahrain) */
+  {0x3C09,      "en"},  /* ??? */
+  {0x3C0A,      "es"},  /* Spanish (Paraguay) */
+  {0x3C0C,      "fr"},  /* ??? */
+  {0x4001,      "ar"},  /* Arabic (Qatar) */
+  {0x4009,      "en"},  /* English (India) */
+  {0x400A,      "es"},  /* Spanish (Bolivia) */
+  {0x4409,      "en"},  /* English (Malaysia) */
+  {0x440A,      "es"},  /* Spanish (El Salvador) */
+  {0x4809,      "en"},  /* English (Singapore) */
+  {0x480A,      "es"},  /* Spanish (Honduras) */
+  {0x4C0A,      "es"},  /* Spanish (Nicaragua) */
+  {0x500A,      "es"},  /* Spanish (Puerto Rico) */
+  {0x540A,      "es"},  /* Spanish (United States) */
+  {0xE40A,      "es"},  /* ??? */
+  {0xE40C,      "fr"},  /* ??? */
+};
+
+static const hb_ot_language_map_t
+hb_mac_language_map[] =
+{
+  {  0, "en"},  /* English */
+  {  1, "fr"},  /* French */
+  {  2, "de"},  /* German */
+  {  3, "it"},  /* Italian */
+  {  4, "nl"},  /* Dutch */
+  {  5, "sv"},  /* Swedish */
+  {  6, "es"},  /* Spanish */
+  {  7, "da"},  /* Danish */
+  {  8, "pt"},  /* Portuguese */
+  {  9, "no"},  /* Norwegian */
+  { 10, "he"},  /* Hebrew */
+  { 11, "ja"},  /* Japanese */
+  { 12, "ar"},  /* Arabic */
+  { 13, "fi"},  /* Finnish */
+  { 14, "el"},  /* Greek */
+  { 15, "is"},  /* Icelandic */
+  { 16, "mt"},  /* Maltese */
+  { 17, "tr"},  /* Turkish */
+  { 18, "hr"},  /* Croatian */
+  { 19, "zh-tw"},       /* Chinese (Traditional) */
+  { 20, "ur"},  /* Urdu */
+  { 21, "hi"},  /* Hindi */
+  { 22, "th"},  /* Thai */
+  { 23, "ko"},  /* Korean */
+  { 24, "lt"},  /* Lithuanian */
+  { 25, "pl"},  /* Polish */
+  { 26, "hu"},  /* Hungarian */
+  { 27, "et"},  /* Estonian */
+  { 28, "lv"},  /* Latvian */
+//{ 29, ""},    /* Sami */
+  { 30, "fo"},  /* Faroese */
+  { 31, "fa"},  /* Farsi/Persian */
+  { 32, "ru"},  /* Russian */
+  { 33, "zh-cn"},       /* Chinese (Simplified) */
+  { 34, "nl"},  /* Flemish */
+  { 35, "ga"},  /* Irish Gaelic */
+  { 36, "sq"},  /* Albanian */
+  { 37, "ro"},  /* Romanian */
+  { 38, "cs"},  /* Czech */
+  { 39, "sk"},  /* Slovak */
+  { 40, "sl"},  /* Slovenian */
+  { 41, "yi"},  /* Yiddish */
+  { 42, "sr"},  /* Serbian */
+  { 43, "mk"},  /* Macedonian */
+  { 44, "bg"},  /* Bulgarian */
+  { 45, "uk"},  /* Ukrainian */
+  { 46, "be"},  /* Byelorussian */
+  { 47, "uz"},  /* Uzbek */
+  { 48, "kk"},  /* Kazakh */
+  { 49, "az"},  /* Azerbaijani (Cyrillic script) */
+  { 50, "az"},  /* Azerbaijani (Arabic script) */
+  { 51, "hy"},  /* Armenian */
+  { 52, "ka"},  /* Georgian */
+  { 53, "mo"},  /* Moldavian */
+  { 54, "ky"},  /* Kirghiz */
+  { 55, "tg"},  /* Tajiki */
+  { 56, "tk"},  /* Turkmen */
+  { 57, "mn"},  /* Mongolian (Mongolian script) */
+  { 58, "mn"},  /* Mongolian (Cyrillic script) */
+  { 59, "ps"},  /* Pashto */
+  { 60, "ku"},  /* Kurdish */
+  { 61, "ks"},  /* Kashmiri */
+  { 62, "sd"},  /* Sindhi */
+  { 63, "bo"},  /* Tibetan */
+  { 64, "ne"},  /* Nepali */
+  { 65, "sa"},  /* Sanskrit */
+  { 66, "mr"},  /* Marathi */
+  { 67, "bn"},  /* Bengali */
+  { 68, "as"},  /* Assamese */
+  { 69, "gu"},  /* Gujarati */
+  { 70, "pa"},  /* Punjabi */
+  { 71, "or"},  /* Oriya */
+  { 72, "ml"},  /* Malayalam */
+  { 73, "kn"},  /* Kannada */
+  { 74, "ta"},  /* Tamil */
+  { 75, "te"},  /* Telugu */
+  { 76, "si"},  /* Sinhalese */
+  { 77, "my"},  /* Burmese */
+  { 78, "km"},  /* Khmer */
+  { 79, "lo"},  /* Lao */
+  { 80, "vi"},  /* Vietnamese */
+  { 81, "id"},  /* Indonesian */
+  { 82, "tl"},  /* Tagalog */
+  { 83, "ms"},  /* Malay (Roman script) */
+  { 84, "ms"},  /* Malay (Arabic script) */
+  { 85, "am"},  /* Amharic */
+  { 86, "ti"},  /* Tigrinya */
+  { 87, "om"},  /* Galla */
+  { 88, "so"},  /* Somali */
+  { 89, "sw"},  /* Swahili */
+  { 90, "rw"},  /* Kinyarwanda/Ruanda */
+  { 91, "rn"},  /* Rundi */
+  { 92, "ny"},  /* Nyanja/Chewa */
+  { 93, "mg"},  /* Malagasy */
+  { 94, "eo"},  /* Esperanto */
+  {128, "cy"},  /* Welsh */
+  {129, "eu"},  /* Basque */
+  {130, "ca"},  /* Catalan */
+  {131, "la"},  /* Latin */
+  {132, "qu"},  /* Quechua */
+  {133, "gn"},  /* Guarani */
+  {134, "ay"},  /* Aymara */
+  {135, "tt"},  /* Tatar */
+  {136, "ug"},  /* Uighur */
+  {137, "dz"},  /* Dzongkha */
+  {138, "jw"},  /* Javanese (Roman script) */
+  {139, "su"},  /* Sundanese (Roman script) */
+  {140, "gl"},  /* Galician */
+  {141, "af"},  /* Afrikaans */
+  {142, "br"},  /* Breton */
+  {143, "iu"},  /* Inuktitut */
+  {144, "gd"},  /* Scottish Gaelic */
+  {145, "gv"},  /* Manx Gaelic */
+  {146, "ga"},  /* Irish Gaelic (with dot above) */
+  {147, "to"},  /* Tongan */
+  {148, "el"},  /* Greek (polytonic) */
+  {149, "ik"},  /* Greenlandic */
+  {150, "az"},  /* Azerbaijani (Roman script) */
+};
+
+
+static hb_language_t
+_hb_ot_name_language_for (unsigned int code,
+                          const hb_ot_language_map_t *array,
+                          unsigned int len)
+{
+  const hb_ot_language_map_t *entry = (const hb_ot_language_map_t *)
+                                      hb_bsearch (&code,
+                                                  array,
+                                                  len,
+                                                  sizeof (array[0]),
+                                                  hb_ot_language_map_t::cmp);
+
+  if (entry)
+    return hb_language_from_string (entry->lang, -1);
+
+  return HB_LANGUAGE_INVALID;
+}
+
+hb_language_t
+_hb_ot_name_language_for_ms_code (unsigned int code)
+{
+  return _hb_ot_name_language_for (code,
+                                   hb_ms_language_map,
+                                   ARRAY_LENGTH (hb_ms_language_map));
+}
+
+hb_language_t
+_hb_ot_name_language_for_mac_code (unsigned int code)
+{
+  return _hb_ot_name_language_for (code,
+                                   hb_mac_language_map,
+                                   ARRAY_LENGTH (hb_mac_language_map));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-language.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_NAME_LANGUAGE_HH
+#define HB_OT_NAME_LANGUAGE_HH
+
+#include "hb.hh"
+
+
+HB_INTERNAL hb_language_t
+_hb_ot_name_language_for_ms_code (unsigned int code);
+
+HB_INTERNAL hb_language_t
+_hb_ot_name_language_for_mac_code (unsigned int code);
+
+
+#endif /* HB_OT_NAME_LANGUAGE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,38 +27,73 @@
 #ifndef HB_OT_NAME_TABLE_HH
 #define HB_OT_NAME_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
+#include "hb-ot-name-language.hh"
+#include "hb-aat-layout.hh"
 
 
 namespace OT {
 
 
+#define entry_score var.u16[0]
+#define entry_index var.u16[1]
+
+
 /*
  * name -- Naming
  * https://docs.microsoft.com/en-us/typography/opentype/spec/name
  */
 #define HB_OT_TAG_name HB_TAG('n','a','m','e')
 
+#define UNSUPPORTED     42
 
 struct NameRecord
 {
-  static int cmp (const void *pa, const void *pb)
+  hb_language_t language (hb_face_t *face) const
   {
-    const NameRecord *a = (const NameRecord *) pa;
-    const NameRecord *b = (const NameRecord *) pb;
-    int ret;
-    ret = b->platformID.cmp (a->platformID);
-    if (ret) return ret;
-    ret = b->encodingID.cmp (a->encodingID);
-    if (ret) return ret;
-    ret = b->languageID.cmp (a->languageID);
-    if (ret) return ret;
-    ret = b->nameID.cmp (a->nameID);
-    if (ret) return ret;
-    return 0;
+    unsigned int p = platformID;
+    unsigned int l = languageID;
+
+    if (p == 3)
+      return _hb_ot_name_language_for_ms_code (l);
+
+    if (p == 1)
+      return _hb_ot_name_language_for_mac_code (l);
+
+    if (p == 0)
+      return _hb_aat_language_get (face, l);
+
+    return HB_LANGUAGE_INVALID;
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  uint16_t score () const
+  {
+    /* Same order as in cmap::find_best_subtable(). */
+    unsigned int p = platformID;
+    unsigned int e = encodingID;
+
+    /* 32-bit. */
+    if (p == 3 && e == 10) return 0;
+    if (p == 0 && e ==  6) return 1;
+    if (p == 0 && e ==  4) return 2;
+
+    /* 16-bit. */
+    if (p == 3 && e ==  1) return 3;
+    if (p == 0 && e ==  3) return 4;
+    if (p == 0 && e ==  2) return 5;
+    if (p == 0 && e ==  1) return 6;
+    if (p == 0 && e ==  0) return 7;
+
+    /* Symbol. */
+    if (p == 3 && e ==  0) return 8;
+
+    /* We treat all Mac Latin names as ASCII only. */
+    if (p == 1 && e ==  0) return 10; /* 10 is magic number :| */
+
+    return UNSUPPORTED;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     /* We can check from base all the way up to the end of string... */
@@ -75,62 +110,168 @@
   DEFINE_SIZE_STATIC (12);
 };
 
+static int
+_hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
+{
+  const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+  const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
+
+  /* Compare by name_id, then language. */
+
+  if (a->name_id != b->name_id)
+    return a->name_id < b->name_id ? -1 : +1;
+
+  if (a->language == b->language) return 0;
+  if (!a->language) return -1;
+  if (!b->language) return +1;
+  return strcmp (hb_language_to_string (a->language),
+                 hb_language_to_string (b->language));
+}
+
+static int
+_hb_ot_name_entry_cmp (const void *pa, const void *pb)
+{
+  /* Compare by name_id, then language, then score, then index. */
+
+  int v = _hb_ot_name_entry_cmp_key (pa, pb);
+  if (v)
+    return v;
+
+  const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
+  const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
+
+  if (a->entry_score != b->entry_score)
+    return a->entry_score < b->entry_score ? -1 : +1;
+
+  if (a->entry_index != b->entry_index)
+    return a->entry_index < b->entry_index ? -1 : +1;
+
+  return 0;
+}
+
 struct name
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_name;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_name;
 
-  inline unsigned int get_name (unsigned int platform_id,
-                                unsigned int encoding_id,
-                                unsigned int language_id,
-                                unsigned int name_id,
-                                void *buffer,
-                                unsigned int buffer_length) const
-  {
-    NameRecord key;
-    key.platformID.set (platform_id);
-    key.encodingID.set (encoding_id);
-    key.languageID.set (language_id);
-    key.nameID.set (name_id);
-    NameRecord *match = (NameRecord *) bsearch (&key, nameRecord, count, sizeof (nameRecord[0]), NameRecord::cmp);
+  unsigned int get_size () const
+  { return min_size + count * nameRecordZ.item_size; }
 
-    if (!match)
-      return 0;
-
-    unsigned int length = MIN (buffer_length, (unsigned int) match->length);
-    memcpy (buffer, (char *) this + stringOffset + match->offset, length);
-    return length;
-  }
-
-  inline unsigned int get_size (void) const
-  { return min_size + count * nameRecord[0].min_size; }
-
-  inline bool sanitize_records (hb_sanitize_context_t *c) const {
+  bool sanitize_records (hb_sanitize_context_t *c) const
+  {
     TRACE_SANITIZE (this);
-    char *string_pool = (char *) this + stringOffset;
+    const void *string_pool = (this+stringOffset).arrayZ;
     unsigned int _count = count;
+    /* Move to run-time?! */
     for (unsigned int i = 0; i < _count; i++)
-      if (!nameRecord[i].sanitize (c, string_pool)) return_trace (false);
+      if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false);
     return_trace (true);
   }
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
                   likely (format == 0 || format == 1) &&
-                  c->check_array (nameRecord, nameRecord[0].static_size, count) &&
-                  sanitize_records (c));
+                  c->check_array (nameRecordZ.arrayZ, count) &&
+                  c->check_range (this, stringOffset));
   }
 
+  struct accelerator_t
+  {
+    void init (hb_face_t *face)
+    {
+      this->table = hb_sanitize_context_t().reference_table<name> (face);
+      assert (this->table.get_length () >= this->table->stringOffset);
+      this->pool = (const char *) (const void *) (this->table+this->table->stringOffset);
+      this->pool_len = this->table.get_length () - this->table->stringOffset;
+      const hb_array_t<const NameRecord> all_names (this->table->nameRecordZ.arrayZ,
+                                                    this->table->count);
+
+      this->names.init ();
+      this->names.alloc (all_names.length);
+
+      for (unsigned int i = 0; i < all_names.length; i++)
+      {
+        hb_ot_name_entry_t *entry = this->names.push ();
+
+        entry->name_id = all_names[i].nameID;
+        entry->language = all_names[i].language (face);
+        entry->entry_score =  all_names[i].score ();
+        entry->entry_index = i;
+      }
+
+      this->names.qsort (_hb_ot_name_entry_cmp);
+      /* Walk and pick best only for each name_id,language pair,
+       * while dropping unsupported encodings. */
+      unsigned int j = 0;
+      for (unsigned int i = 0; i < this->names.length; i++)
+      {
+        if (this->names[i].entry_score == UNSUPPORTED ||
+            this->names[i].language == HB_LANGUAGE_INVALID)
+          continue;
+        if (i &&
+            this->names[i - 1].name_id  == this->names[i].name_id &&
+            this->names[i - 1].language == this->names[i].language)
+          continue;
+        this->names[j++] = this->names[i];
+      }
+      this->names.resize (j);
+    }
+
+    void fini ()
+    {
+      this->names.fini ();
+      this->table.destroy ();
+    }
+
+    int get_index (hb_ot_name_id_t   name_id,
+                          hb_language_t     language,
+                          unsigned int     *width=nullptr) const
+    {
+      const hb_ot_name_entry_t key = {name_id, {0}, language};
+      const hb_ot_name_entry_t *entry = (const hb_ot_name_entry_t *)
+                                        hb_bsearch (&key,
+                                                    (const hb_ot_name_entry_t *) this->names,
+                                                    this->names.length,
+                                                    sizeof (key),
+                                                    _hb_ot_name_entry_cmp_key);
+      if (!entry)
+        return -1;
+
+      if (width)
+        *width = entry->entry_score < 10 ? 2 : 1;
+
+      return entry->entry_index;
+    }
+
+    hb_bytes_t get_name (unsigned int idx) const
+    {
+      const hb_array_t<const NameRecord> all_names (table->nameRecordZ.arrayZ, table->count);
+      const NameRecord &record = all_names[idx];
+      const hb_bytes_t string_pool (pool, pool_len);
+      return string_pool.sub_array (record.offset, record.length);
+    }
+
+    private:
+    const char *pool;
+    unsigned int pool_len;
+    public:
+    hb_blob_ptr_t<name> table;
+    hb_vector_t<hb_ot_name_entry_t> names;
+  };
+
   /* We only implement format 0 for now. */
   HBUINT16      format;                 /* Format selector (=0/1). */
   HBUINT16      count;                  /* Number of name records. */
-  Offset16      stringOffset;           /* Offset to start of string storage (from start of table). */
-  NameRecord    nameRecord[VAR];        /* The name records where count is the number of records. */
+  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
+                stringOffset;           /* Offset to start of string storage (from start of table). */
+  UnsizedArrayOf<NameRecord>
+                nameRecordZ;            /* The name records where count is the number of records. */
   public:
-  DEFINE_SIZE_ARRAY (6, nameRecord);
+  DEFINE_SIZE_ARRAY (6, nameRecordZ);
 };
 
+struct name_accelerator_t : name::accelerator_t {};
 
 } /* namespace OT */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,224 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#include "hb-ot-name-table.hh"
+
+#include "hb-ot-face.hh"
+#include "hb-utf.hh"
+
+
+/**
+ * SECTION:hb-ot-name
+ * @title: hb-ot-name
+ * @short_description: OpenType font name information
+ * @include: hb-ot.h
+ *
+ * Functions for fetching name strings from OpenType fonts.
+ **/
+
+
+/**
+ * hb_ot_name_list_names:
+ * @face: font face.
+ * @num_entries: (out) (allow-none): number of returned entries.
+ *
+ * Enumerates all available name IDs and language combinations. Returned
+ * array is owned by the @face and should not be modified.  It can be
+ * used as long as @face is alive.
+ *
+ * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
+ * Since: 2.1.0
+ **/
+const hb_ot_name_entry_t *
+hb_ot_name_list_names (hb_face_t    *face,
+                       unsigned int *num_entries /* OUT */)
+{
+  const OT::name_accelerator_t &name = *face->table.name;
+  if (num_entries) *num_entries = name.names.length;
+  return (const hb_ot_name_entry_t *) name.names;
+}
+
+
+template <typename in_utf_t, typename out_utf_t>
+static inline unsigned int
+hb_ot_name_convert_utf (hb_bytes_t                       bytes,
+                        unsigned int                    *text_size /* IN/OUT */,
+                        typename out_utf_t::codepoint_t *text /* OUT */)
+{
+  unsigned int src_len = bytes.length / sizeof (typename in_utf_t::codepoint_t);
+  const typename in_utf_t::codepoint_t *src = (const typename in_utf_t::codepoint_t *) bytes.arrayZ;
+  const typename in_utf_t::codepoint_t *src_end = src + src_len;
+
+  typename out_utf_t::codepoint_t *dst = text;
+
+  hb_codepoint_t unicode;
+  const hb_codepoint_t replacement = HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT;
+
+  if (text_size && *text_size)
+  {
+    (*text_size)--; /* Same room for NUL-termination. */
+    const typename out_utf_t::codepoint_t *dst_end = text + *text_size;
+
+    while (src < src_end && dst < dst_end)
+    {
+      const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
+      typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
+      if (dst_next == dst)
+        break; /* Out-of-room. */
+
+      dst = dst_next;
+      src = src_next;
+    };
+
+    *text_size = dst - text;
+    *dst = 0; /* NUL-terminate. */
+  }
+
+  /* Accumulate length of rest. */
+  unsigned int dst_len = dst - text;
+  while (src < src_end)
+  {
+    src = in_utf_t::next (src, src_end, &unicode, replacement);
+    dst_len += out_utf_t::encode_len (unicode);
+  };
+  return dst_len;
+}
+
+template <typename utf_t>
+static inline unsigned int
+hb_ot_name_get_utf (hb_face_t       *face,
+                    hb_ot_name_id_t  name_id,
+                    hb_language_t    language,
+                    unsigned int    *text_size /* IN/OUT */,
+                    typename utf_t::codepoint_t *text /* OUT */)
+{
+  const OT::name_accelerator_t &name = *face->table.name;
+
+  if (!language)
+    language = hb_language_from_string ("en", 2);
+
+  unsigned int width;
+  int idx = name.get_index (name_id, language, &width);
+  if (idx != -1)
+  {
+    hb_bytes_t bytes = name.get_name (idx);
+
+    if (width == 2) /* UTF16-BE */
+      return hb_ot_name_convert_utf<hb_utf16_be_t, utf_t> (bytes, text_size, text);
+
+    if (width == 1) /* ASCII */
+      return hb_ot_name_convert_utf<hb_ascii_t, utf_t> (bytes, text_size, text);
+  }
+
+  if (text_size)
+  {
+    if (*text_size)
+      *text = 0;
+    *text_size = 0;
+  }
+  return 0;
+}
+
+/**
+ * hb_ot_name_get_utf8:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-8 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf8 (hb_face_t       *face,
+                     hb_ot_name_id_t  name_id,
+                     hb_language_t    language,
+                     unsigned int    *text_size /* IN/OUT */,
+                     char            *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size,
+                                        (hb_utf8_t::codepoint_t *) text);
+}
+
+/**
+ * hb_ot_name_get_utf16:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-16 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf16 (hb_face_t       *face,
+                      hb_ot_name_id_t  name_id,
+                      hb_language_t    language,
+                      unsigned int    *text_size /* IN/OUT */,
+                      uint16_t        *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text);
+}
+
+/**
+ * hb_ot_name_get_utf32:
+ * @face: font face.
+ * @name_id: OpenType name identifier to fetch.
+ * @language: language to fetch the name for.
+ * @text_size: (inout) (allow-none): input size of @text buffer, and output size of
+ *                                   text written to buffer.
+ * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into.
+ *
+ * Fetches a font name from the OpenType 'name' table.
+ * If @language is #HB_LANGUAGE_INVALID, English ("en") is assumed.
+ * Returns string in UTF-32 encoding.
+ *
+ * Returns: full length of the requested string, or 0 if not found.
+ * Since: 2.1.0
+ **/
+unsigned int
+hb_ot_name_get_utf32 (hb_face_t       *face,
+                      hb_ot_name_id_t  name_id,
+                      hb_language_t    language,
+                      unsigned int    *text_size /* IN/OUT */,
+                      uint32_t        *text      /* OUT */)
+{
+  return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-name.h	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_NAME_H
+#define HB_OT_NAME_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+
+/**
+ * hb_ot_name_id_t:
+ * @HB_OT_NAME_ID_INVALID: Value to represent a nonexistent name ID.
+ *
+ * An integral type representing an OpenType 'name' table name identifier.
+ * There are predefined name IDs, as well as name IDs return from other
+ * API.  These can be used to fetch name strings from a font face.
+ *
+ * Since: 2.0.0
+ **/
+enum
+{
+  HB_OT_NAME_ID_COPYRIGHT               = 0,
+  HB_OT_NAME_ID_FONT_FAMILY             = 1,
+  HB_OT_NAME_ID_FONT_SUBFAMILY          = 2,
+  HB_OT_NAME_ID_UNIQUE_ID               = 3,
+  HB_OT_NAME_ID_FULL_NAME               = 4,
+  HB_OT_NAME_ID_VERSION_STRING          = 5,
+  HB_OT_NAME_ID_POSTSCRIPT_NAME         = 6,
+  HB_OT_NAME_ID_TRADEMARK               = 7,
+  HB_OT_NAME_ID_MANUFACTURER            = 8,
+  HB_OT_NAME_ID_DESIGNER                = 9,
+  HB_OT_NAME_ID_DESCRIPTION             = 10,
+  HB_OT_NAME_ID_VENDOR_URL              = 11,
+  HB_OT_NAME_ID_DESIGNER_URL            = 12,
+  HB_OT_NAME_ID_LICENSE                 = 13,
+  HB_OT_NAME_ID_LICENSE_URL             = 14,
+/*HB_OT_NAME_ID_RESERVED                = 15,*/
+  HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY      = 16,
+  HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY   = 17,
+  HB_OT_NAME_ID_MAC_FULL_NAME           = 18,
+  HB_OT_NAME_ID_SAMPLE_TEXT             = 19,
+  HB_OT_NAME_ID_CID_FINDFONT_NAME       = 20,
+  HB_OT_NAME_ID_WWS_FAMILY              = 21,
+  HB_OT_NAME_ID_WWS_SUBFAMILY           = 22,
+  HB_OT_NAME_ID_LIGHT_BACKGROUND        = 23,
+  HB_OT_NAME_ID_DARK_BACKGROUND         = 24,
+  HB_OT_NAME_ID_VARIATIONS_PS_PREFIX    = 25,
+
+  HB_OT_NAME_ID_INVALID                 = 0xFFFF
+};
+
+typedef unsigned int hb_ot_name_id_t;
+
+
+/**
+ * hb_ot_name_entry_t:
+ * @name_id: name ID
+ * @language: language
+ *
+ * Structure representing a name ID in a particular language.
+ *
+ * Since: 2.1.0
+ **/
+typedef struct hb_ot_name_entry_t
+{
+  hb_ot_name_id_t name_id;
+  /*< private >*/
+  hb_var_int_t    var;
+  /*< public >*/
+  hb_language_t   language;
+} hb_ot_name_entry_t;
+
+HB_EXTERN const hb_ot_name_entry_t *
+hb_ot_name_list_names (hb_face_t    *face,
+                       unsigned int *num_entries /* OUT */);
+
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf8 (hb_face_t       *face,
+                     hb_ot_name_id_t  name_id,
+                     hb_language_t    language,
+                     unsigned int    *text_size /* IN/OUT */,
+                     char            *text      /* OUT */);
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf16 (hb_face_t       *face,
+                      hb_ot_name_id_t  name_id,
+                      hb_language_t    language,
+                      unsigned int    *text_size /* IN/OUT */,
+                      uint16_t        *text      /* OUT */);
+
+HB_EXTERN unsigned int
+hb_ot_name_get_utf32 (hb_face_t       *face,
+                      hb_ot_name_id_t  name_id,
+                      hb_language_t    language,
+                      unsigned int    *text_size /* IN/OUT */,
+                      uint32_t        *text      /* OUT */);
+
+
+HB_END_DECLS
+
+#endif /* HB_OT_NAME_H */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2011,2012  Google, Inc.
+ * Copyright © 2018  Ebrahim Byagowi
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -27,36 +28,131 @@
 #ifndef HB_OT_OS2_TABLE_HH
 #define HB_OT_OS2_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 #include "hb-ot-os2-unicode-ranges.hh"
-#include "hb-subset-plan.hh"
 
-namespace OT {
+#include "hb-set.hh"
 
 /*
  * OS/2 and Windows Metrics
  * https://docs.microsoft.com/en-us/typography/opentype/spec/os2
  */
-#define HB_OT_TAG_os2 HB_TAG('O','S','/','2')
+#define HB_OT_TAG_OS2 HB_TAG('O','S','/','2')
+
 
-struct os2
+namespace OT {
+
+struct OS2V1Tail
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_os2;
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBUINT32      ulCodePageRange1;
+  HBUINT32      ulCodePageRange2;
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+struct OS2V2Tail
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  HBINT16       sxHeight;
+  HBINT16       sCapHeight;
+  HBUINT16      usDefaultChar;
+  HBUINT16      usBreakChar;
+  HBUINT16      usMaxContext;
+  public:
+  DEFINE_SIZE_STATIC (10);
+};
+
+struct OS2V5Tail
+{
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
   }
 
-  inline bool subset (hb_subset_plan_t *plan) const
+  public:
+  HBUINT16      usLowerOpticalPointSize;
+  HBUINT16      usUpperOpticalPointSize;
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct OS2
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_OS2;
+
+  bool has_data () const { return this != &Null (OS2); }
+
+  const OS2V1Tail &v1 () const { return version >= 1 ? v1X : Null (OS2V1Tail); }
+  const OS2V2Tail &v2 () const { return version >= 2 ? v2X : Null (OS2V2Tail); }
+  const OS2V5Tail &v5 () const { return version >= 5 ? v5X : Null (OS2V5Tail); }
+
+  enum selection_flag_t {
+    ITALIC              = 1u<<0,
+    UNDERSCORE          = 1u<<1,
+    NEGATIVE            = 1u<<2,
+    OUTLINED            = 1u<<3,
+    STRIKEOUT           = 1u<<4,
+    BOLD                = 1u<<5,
+    REGULAR             = 1u<<6,
+    USE_TYPO_METRICS    = 1u<<7,
+    WWS                 = 1u<<8,
+    OBLIQUE             = 1u<<9
+  };
+
+  bool is_italic () const       { return fsSelection & ITALIC; }
+  bool is_oblique () const      { return fsSelection & OBLIQUE; }
+  bool is_typo_metrics () const { return fsSelection & USE_TYPO_METRICS; }
+
+  enum width_class_t {
+    FWIDTH_ULTRA_CONDENSED      = 1, /* 50% */
+    FWIDTH_EXTRA_CONDENSED      = 2, /* 62.5% */
+    FWIDTH_CONDENSED            = 3, /* 75% */
+    FWIDTH_SEMI_CONDENSED       = 4, /* 87.5% */
+    FWIDTH_NORMAL               = 5, /* 100% */
+    FWIDTH_SEMI_EXPANDED        = 6, /* 112.5% */
+    FWIDTH_EXPANDED             = 7, /* 125% */
+    FWIDTH_EXTRA_EXPANDED       = 8, /* 150% */
+    FWIDTH_ULTRA_EXPANDED       = 9  /* 200% */
+  };
+
+  float get_width () const
   {
-    hb_blob_t *os2_blob = OT::Sanitizer<OT::os2>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_os2));
+    switch (usWidthClass) {
+    case FWIDTH_ULTRA_CONDENSED:return 50.f;
+    case FWIDTH_EXTRA_CONDENSED:return 62.5f;
+    case FWIDTH_CONDENSED:      return 75.f;
+    case FWIDTH_SEMI_CONDENSED: return 87.5f;
+    default:
+    case FWIDTH_NORMAL:         return 100.f;
+    case FWIDTH_SEMI_EXPANDED:  return 112.5f;
+    case FWIDTH_EXPANDED:       return 125.f;
+    case FWIDTH_EXTRA_EXPANDED: return 150.f;
+    case FWIDTH_ULTRA_EXPANDED: return 200.f;
+    }
+  }
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *os2_blob = hb_sanitize_context_t ().reference_table<OS2> (plan->source);
     hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
     // TODO(grieger): move to hb_blob_copy_writable_or_fail
     hb_blob_destroy (os2_blob);
 
-    OT::os2 *os2_prime = (OT::os2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
+    OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
     if (unlikely (!os2_prime)) {
       hb_blob_destroy (os2_prime_blob);
       return false;
@@ -68,21 +164,21 @@
     os2_prime->usLastCharIndex.set (max_cp);
 
     _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
-    bool result = plan->add_table (HB_OT_TAG_os2, os2_prime_blob);
+    bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob);
 
     hb_blob_destroy (os2_prime_blob);
     return result;
   }
 
-  inline void _update_unicode_ranges (const hb_set_t *codepoints,
-                                      HBUINT32 ulUnicodeRange[4]) const
+  void _update_unicode_ranges (const hb_set_t *codepoints,
+                               HBUINT32 ulUnicodeRange[4]) const
   {
     for (unsigned int i = 0; i < 4; i++)
       ulUnicodeRange[i].set (0);
 
     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
     while (codepoints->next (&cp)) {
-      unsigned int bit = hb_get_unicode_range_bit (cp);
+      unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
       if (bit < 128)
       {
         unsigned int block = bit / 32;
@@ -100,7 +196,7 @@
     }
   }
 
-  static inline void find_min_and_max_codepoint (const hb_set_t *codepoints,
+  static void find_min_and_max_codepoint (const hb_set_t *codepoints,
                                                  uint16_t *min_cp, /* OUT */
                                                  uint16_t *max_cp  /* OUT */)
   {
@@ -119,17 +215,21 @@
   };
 
   // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
-  inline font_page_t get_font_page () const
+  font_page_t get_font_page () const
+  { return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
-    if (version != 0)
-      return (font_page_t) 0;
-    return (font_page_t) (fsSelection & 0xFF00);
+    TRACE_SANITIZE (this);
+    if (unlikely (!c->check_struct (this))) return_trace (false);
+    if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false);
+    if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false);
+    if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false);
+    return_trace (true);
   }
 
   public:
   HBUINT16      version;
-
-  /* Version 0 */
   HBINT16       xAvgCharWidth;
   HBUINT16      usWeightClass;
   HBUINT16      usWidthClass;
@@ -156,24 +256,11 @@
   HBINT16       sTypoLineGap;
   HBUINT16      usWinAscent;
   HBUINT16      usWinDescent;
-
-  /* Version 1 */
-  //HBUINT32    ulCodePageRange1;
-  //HBUINT32    ulCodePageRange2;
-
-  /* Version 2 */
-  //HBINT16     sxHeight;
-  //HBINT16     sCapHeight;
-  //HBUINT16    usDefaultChar;
-  //HBUINT16    usBreakChar;
-  //HBUINT16    usMaxContext;
-
-  /* Version 5 */
-  //HBUINT16    usLowerOpticalPointSize;
-  //HBUINT16    usUpperOpticalPointSize;
-
+  OS2V1Tail     v1X;
+  OS2V2Tail     v2X;
+  OS2V5Tail     v5X;
   public:
-  DEFINE_SIZE_STATIC (78);
+  DEFINE_SIZE_MIN (78);
 };
 
 } /* namespace OT */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-unicode-ranges.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-os2-unicode-ranges.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,19 +27,33 @@
 #ifndef HB_OT_OS2_UNICODE_RANGES_HH
 #define HB_OT_OS2_UNICODE_RANGES_HH
 
-#include "hb-private.hh"
-#include "hb-dsalgs.hh"
+#include "hb.hh"
 
 namespace OT {
 
-struct Range {
+struct OS2Range
+{
+  static int
+  cmp (const void *_key, const void *_item)
+  {
+    hb_codepoint_t cp = *((hb_codepoint_t *) _key);
+    const OS2Range *range = (OS2Range *) _item;
+
+    if (cp < range->start)
+      return -1;
+    else if (cp <= range->end)
+      return 0;
+    else
+      return +1;
+  }
+
   hb_codepoint_t start;
   hb_codepoint_t end;
   unsigned int bit;
 };
 
-/* Note: The contents of this array was generated using src/gen-unicode-ranges.py. */
-static Range os2UnicodeRangesSorted[] =
+/* Note: The contents of this array was generated using gen-os2-unicode-ranges.py. */
+static const OS2Range _hb_os2_unicode_ranges[] =
 {
   {     0x0,     0x7F,   0}, // Basic Latin
   {    0x80,     0xFF,   1}, // Latin-1 Supplement
@@ -212,31 +226,17 @@
   {0x100000, 0x10FFFD,  90}, // Private Use (plane 16)
 };
 
-static int
-_compare_range (const void *_key, const void *_item, void *_arg)
-{
-  hb_codepoint_t cp = *((hb_codepoint_t *) _key);
-  const Range *range = (Range *) _item;
-
-  if (cp < range->start)
-    return -1;
-  else if (cp <= range->end)
-    return 0;
-  else
-    return 1;
-}
-
 /**
- * hb_get_unicode_range_bit:
- * Returns the bit to be set in os/2 ulUnicodeRange for a given codepoint.
+ * _hb_ot_os2_get_unicode_range_bit:
+ * Returns the bit to be set in os/2 ulUnicodeOS2Range for a given codepoint.
  **/
 static unsigned int
-hb_get_unicode_range_bit (hb_codepoint_t cp)
+_hb_ot_os2_get_unicode_range_bit (hb_codepoint_t cp)
 {
-  Range *range = (Range*) hb_bsearch_r (&cp, os2UnicodeRangesSorted,
-                                        sizeof (os2UnicodeRangesSorted) / sizeof(Range),
-                                        sizeof(Range),
-                                        _compare_range, nullptr);
+  OS2Range *range = (OS2Range*) hb_bsearch (&cp, _hb_os2_unicode_ranges,
+                                            ARRAY_LENGTH (_hb_os2_unicode_ranges),
+                                            sizeof (OS2Range),
+                                            OS2Range::cmp);
   if (range != nullptr)
     return range->bit;
   return -1;
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-macroman.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-macroman.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,7 @@
 #ifndef HB_OT_POST_MACROMAN_HH
 #if 0 /* Make checks happy. */
 #define HB_OT_POST_MACROMAN_HH
-#include "hb-private.hh"
+#include "hb.hh"
 #endif
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-post-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,9 +27,7 @@
 #ifndef HB_OT_POST_TABLE_HH
 #define HB_OT_POST_TABLE_HH
 
-#include "hb-open-type-private.hh"
-#include "hb-dsalgs.hh"
-#include "hb-subset-plan.hh"
+#include "hb-open-type.hh"
 
 #define HB_STRING_ARRAY_NAME format1_names
 #define HB_STRING_ARRAY_LIST "hb-ot-post-macroman.hh"
@@ -51,47 +49,39 @@
 
 struct postV2Tail
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  friend struct post;
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (glyphNameIndex.sanitize (c));
   }
 
-  ArrayOf<HBUINT16>glyphNameIndex;      /* This is not an offset, but is the
+  protected:
+  ArrayOf<HBUINT16>     glyphNameIndex; /* This is not an offset, but is the
                                          * ordinal number of the glyph in 'post'
                                          * string tables. */
-  HBUINT8               namesX[VAR];            /* Glyph names with length bytes [variable]
+/*UnsizedArrayOf<HBUINT8>
+                        namesX;*/       /* Glyph names with length bytes [variable]
                                          * (a Pascal string). */
 
-  DEFINE_SIZE_ARRAY2 (2, glyphNameIndex, namesX);
+  public:
+  DEFINE_SIZE_ARRAY (2, glyphNameIndex);
 };
 
 struct post
 {
-  static const hb_tag_t tableTag = HB_OT_TAG_post;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    if (unlikely (!c->check_struct (this)))
-      return_trace (false);
-    if (version.to_int () == 0x00020000)
-    {
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*this);
-      return_trace (v2.sanitize (c));
-    }
-    return_trace (true);
-  }
-
-  inline bool subset (hb_subset_plan_t *plan) const
+  bool subset (hb_subset_plan_t *plan) const
   {
     unsigned int post_prime_length;
-    hb_blob_t *post_blob = OT::Sanitizer<post>().sanitize (hb_face_reference_table (plan->source, HB_OT_TAG_post));
-    hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::static_size);
+    hb_blob_t *post_blob = hb_sanitize_context_t ().reference_table<post>(plan->source);
+    hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::min_size);
     post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length);
     hb_blob_destroy (post_blob);
 
-    if (unlikely (!post_prime || post_prime_length != post::static_size))
+    if (unlikely (!post_prime || post_prime_length != post::min_size))
     {
       hb_blob_destroy (post_prime_blob);
       DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length);
@@ -107,63 +97,58 @@
 
   struct accelerator_t
   {
-    inline void init (hb_face_t *face)
+    void init (hb_face_t *face)
     {
       index_to_offset.init ();
 
-      blob = Sanitizer<post>().sanitize (face->reference_table (HB_OT_TAG_post));
-      const post *table = blob->as<post> ();
-      unsigned int table_length = blob->length;
+      table = hb_sanitize_context_t ().reference_table<post> (face);
+      unsigned int table_length = table.get_length ();
 
       version = table->version.to_int ();
-      if (version != 0x00020000)
-        return;
+      if (version != 0x00020000) return;
 
-      const postV2Tail &v2 = StructAfter<postV2Tail> (*table);
+      const postV2Tail &v2 = table->v2X;
 
       glyphNameIndex = &v2.glyphNameIndex;
       pool = &StructAfter<uint8_t> (v2.glyphNameIndex);
 
-      const uint8_t *end = (uint8_t *) table + table_length;
-      for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data)
+      const uint8_t *end = (const uint8_t *) (const void *) table + table_length;
+      for (const uint8_t *data = pool;
+           index_to_offset.length < 65535 && data < end && data + *data < end;
+           data += 1 + *data)
         index_to_offset.push (data - pool);
     }
-    inline void fini (void)
+    void fini ()
     {
       index_to_offset.fini ();
-      free (gids_sorted_by_name);
+      free (gids_sorted_by_name.get ());
+      table.destroy ();
     }
 
-    inline bool get_glyph_name (hb_codepoint_t glyph,
-                                char *buf, unsigned int buf_len) const
+    bool get_glyph_name (hb_codepoint_t glyph,
+                         char *buf, unsigned int buf_len) const
     {
       hb_bytes_t s = find_glyph_name (glyph);
-      if (!s.len)
-        return false;
-      if (!buf_len)
-        return true;
-      if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
-        return false;
-      strncpy (buf, s.bytes, s.len);
-      buf[s.len] = '\0';
+      if (!s.length) return false;
+      if (!buf_len) return true;
+      unsigned int len = MIN (buf_len - 1, s.length);
+      strncpy (buf, s.arrayZ, len);
+      buf[len] = '\0';
       return true;
     }
 
-    inline bool get_glyph_from_name (const char *name, int len,
-                                     hb_codepoint_t *glyph) const
+    bool get_glyph_from_name (const char *name, int len,
+                              hb_codepoint_t *glyph) const
     {
       unsigned int count = get_glyph_count ();
-      if (unlikely (!count))
-        return false;
+      if (unlikely (!count)) return false;
 
-      if (len < 0)
-        len = strlen (name);
+      if (len < 0) len = strlen (name);
 
-      if (unlikely (!len))
-        return false;
+      if (unlikely (!len)) return false;
 
     retry:
-      uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
+      uint16_t *gids = gids_sorted_by_name.get ();
 
       if (unlikely (!gids))
       {
@@ -175,14 +160,16 @@
           gids[i] = i;
         hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
 
-        if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) {
+        if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
+        {
           free (gids);
           goto retry;
         }
       }
 
       hb_bytes_t st (name, len);
-      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
+      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (hb_addressof (st), gids, count,
+                                                             sizeof (gids[0]), cmp_key, (void *) this);
       if (gid)
       {
         *glyph = *gid;
@@ -194,7 +181,7 @@
 
     protected:
 
-    inline unsigned int get_glyph_count (void) const
+    unsigned int get_glyph_count () const
     {
       if (version == 0x00010000)
         return NUM_FORMAT1_NAMES;
@@ -205,7 +192,7 @@
       return 0;
     }
 
-    static inline int cmp_gids (const void *pa, const void *pb, void *arg)
+    static int cmp_gids (const void *pa, const void *pb, void *arg)
     {
       const accelerator_t *thiz = (const accelerator_t *) arg;
       uint16_t a = * (const uint16_t *) pa;
@@ -213,7 +200,7 @@
       return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a));
     }
 
-    static inline int cmp_key (const void *pk, const void *po, void *arg)
+    static int cmp_key (const void *pk, const void *po, void *arg)
     {
       const accelerator_t *thiz = (const accelerator_t *) arg;
       const hb_bytes_t *key = (const hb_bytes_t *) pk;
@@ -221,7 +208,7 @@
       return thiz->find_glyph_name (o).cmp (*key);
     }
 
-    inline hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const
+    hb_bytes_t find_glyph_name (hb_codepoint_t glyph) const
     {
       if (version == 0x00010000)
       {
@@ -239,9 +226,9 @@
         return format1_names (index);
       index -= NUM_FORMAT1_NAMES;
 
-      if (index >= index_to_offset.len)
+      if (index >= index_to_offset.length)
         return hb_bytes_t ();
-      unsigned int offset = index_to_offset.arrayZ[index];
+      unsigned int offset = index_to_offset[index];
 
       const uint8_t *data = pool + offset;
       unsigned int name_length = *data;
@@ -251,14 +238,23 @@
     }
 
     private:
-    hb_blob_t *blob;
+    hb_blob_ptr_t<post> table;
     uint32_t version;
     const ArrayOf<HBUINT16> *glyphNameIndex;
-    hb_vector_t<uint32_t, 1> index_to_offset;
+    hb_vector_t<uint32_t> index_to_offset;
     const uint8_t *pool;
-    mutable uint16_t *gids_sorted_by_name;
+    hb_atomic_ptr_t<uint16_t *> gids_sorted_by_name;
   };
 
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          (version.to_int () == 0x00010000 ||
+                           (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
+                           version.to_int () == 0x00030000)));
+  }
+
   public:
   FixedVersion<>version;                /* 0x00010000 for version 1.0
                                          * 0x00020000 for version 2.0
@@ -291,10 +287,12 @@
                                          * is downloaded as a Type 1 font. */
   HBUINT32      maxMemType1;            /* Maximum memory usage when an OpenType font
                                          * is downloaded as a Type 1 font. */
-/*postV2Tail    v2[VAR];*/
-  DEFINE_SIZE_STATIC (32);
+  postV2Tail    v2X;
+  DEFINE_SIZE_MIN (32);
 };
 
+struct post_accelerator_t : post::accelerator_t {};
+
 } /* namespace OT */
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-fallback.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-fallback.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,9 +27,9 @@
 #ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
 #define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-ot-shape-private.hh"
+#include "hb-ot-shape.hh"
 #include "hb-ot-layout-gsub-table.hh"
 
 
@@ -79,18 +79,15 @@
    * May not be good-enough for presidential candidate interviews, but good-enough for us... */
   hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
 
-  OT::Supplier<OT::GlyphID> glyphs_supplier      (glyphs, num_glyphs);
-  OT::Supplier<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
 
   /* Each glyph takes four bytes max, and there's some overhead. */
   char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
-  OT::hb_serialize_context_t c (buf, sizeof (buf));
+  hb_serialize_context_t c (buf, sizeof (buf));
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
   bool ret = lookup->serialize_single (&c,
                                        OT::LookupFlag::IgnoreMarks,
-                                       glyphs_supplier,
-                                       substitutes_supplier,
-                                       num_glyphs);
+                                       hb_array (glyphs, num_glyphs),
+                                       hb_array (substitutes, num_glyphs));
   c.end_serialize ();
   /* TODO sanitize the results? */
 
@@ -155,25 +152,18 @@
   if (!num_ligatures)
     return nullptr;
 
-  OT::Supplier<OT::GlyphID>   first_glyphs_supplier                      (first_glyphs, num_first_glyphs);
-  OT::Supplier<unsigned int > ligature_per_first_glyph_count_supplier    (ligature_per_first_glyph_count_list, num_first_glyphs);
-  OT::Supplier<OT::GlyphID>   ligatures_supplier                         (ligature_list, num_ligatures);
-  OT::Supplier<unsigned int > component_count_supplier                   (component_count_list, num_ligatures);
-  OT::Supplier<OT::GlyphID>   component_supplier                         (component_list, num_ligatures);
 
   /* 16 bytes per ligature ought to be enough... */
   char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
-  OT::hb_serialize_context_t c (buf, sizeof (buf));
+  hb_serialize_context_t c (buf, sizeof (buf));
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
   bool ret = lookup->serialize_ligature (&c,
                                          OT::LookupFlag::IgnoreMarks,
-                                         first_glyphs_supplier,
-                                         ligature_per_first_glyph_count_supplier,
-                                         num_first_glyphs,
-                                         ligatures_supplier,
-                                         component_count_supplier,
-                                         component_supplier);
-
+                                         hb_array (first_glyphs, num_first_glyphs),
+                                         hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
+                                         hb_array (ligature_list, num_ligatures),
+                                         hb_array (component_count_list, num_ligatures),
+                                         hb_array (component_list, num_ligatures));
   c.end_serialize ();
   /* TODO sanitize the results? */
 
@@ -195,19 +185,15 @@
 
 struct arabic_fallback_plan_t
 {
-  ASSERT_POD ();
-
   unsigned int num_lookups;
   bool free_lookups;
 
   hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
   OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
-  hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+  OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
 };
 
-static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
-
-#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
+#if defined(_WIN32) && !defined(HB_NO_WIN1256)
 #define HB_WITH_WIN1256
 #endif
 
@@ -215,16 +201,20 @@
 #include "hb-ot-shape-complex-arabic-win1256.hh"
 #endif
 
-struct ManifestLookup {
+struct ManifestLookup
+{
+  public:
   OT::Tag tag;
   OT::OffsetTo<OT::SubstLookup> lookupOffset;
+  public:
+  DEFINE_SIZE_STATIC (6);
 };
 typedef OT::ArrayOf<ManifestLookup> Manifest;
 
 static bool
-arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan,
-                                   const hb_ot_shape_plan_t *plan,
-                                   hb_font_t *font)
+arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,
+                                   const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                   hb_font_t *font HB_UNUSED)
 {
 #ifdef HB_WITH_WIN1256
   /* Does this font look like it's Windows-1256-encoded? */
@@ -299,7 +289,7 @@
 {
   arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
   if (unlikely (!fallback_plan))
-    return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+    return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 
   fallback_plan->num_lookups = 0;
   fallback_plan->free_lookups = false;
@@ -314,14 +304,15 @@
   if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
     return fallback_plan;
 
+  assert (fallback_plan->num_lookups == 0);
   free (fallback_plan);
-  return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+  return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 }
 
 static void
 arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
 {
-  if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
+  if (!fallback_plan || fallback_plan->num_lookups == 0)
     return;
 
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-struct arabic_shape_plan_t;
-
-HB_INTERNAL void *
-data_create_arabic (const hb_ot_shape_plan_t *plan);
-
-HB_INTERNAL void
-data_destroy_arabic (void *data);
-
-HB_INTERNAL void
-setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
-                         hb_buffer_t               *buffer,
-                         hb_script_t                script);
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-win1256.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic-win1256.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -313,7 +313,7 @@
  * Include a second time to get the table data...
  */
 #if 0
-#include "hb-private.hh" /* Make check-includes.sh happy. */
+#include "hb.hh" /* Make check-includes.sh happy. */
 #endif
 #ifdef OT_MEASURE
 #include "hb-ot-shape-complex-arabic-win1256.hh"
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,10 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-ot-shape-complex-arabic-private.hh"
-#include "hb-ot-shape-private.hh"
+#include "hb.hh"
+#include "hb-ot-shape-complex-arabic.hh"
+#include "hb-ot-shape.hh"
 
 
 /* buffer var allocations */
@@ -160,11 +159,6 @@
 
 
 static void
-nuke_joiners (const hb_ot_shape_plan_t *plan,
-              hb_font_t *font,
-              hb_buffer_t *buffer);
-
-static void
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
                        hb_font_t *font,
                        hb_buffer_t *buffer);
@@ -201,32 +195,38 @@
    * work correctly.  See https://github.com/harfbuzz/harfbuzz/issues/505
    */
 
-  map->add_gsub_pause (nuke_joiners);
 
-  map->add_global_bool_feature (HB_TAG('s','t','c','h'));
+  map->enable_feature (HB_TAG('s','t','c','h'));
   map->add_gsub_pause (record_stch);
 
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
 
   map->add_gsub_pause (nullptr);
 
   for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
   {
     bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
-    map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE);
+    map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE);
     map->add_gsub_pause (nullptr);
   }
 
-  map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK);
+  /* Normally, Unicode says a ZWNJ means "don't ligate".  In Arabic script
+   * however, it says a ZWJ should also mean "don't ligate".  So we run
+   * the main ligating features as MANUAL_ZWJ. */
+
+  map->enable_feature (HB_TAG('r','l','i','g'), F_MANUAL_ZWJ | F_HAS_FALLBACK);
+
   if (plan->props.script == HB_SCRIPT_ARABIC)
     map->add_gsub_pause (arabic_fallback_shape);
 
   /* No pause after rclt.  See 98460779bae19e4d64d29461ff154b3527bf8420. */
-  map->add_global_bool_feature (HB_TAG('r','c','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
+  map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
+  map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
   map->add_gsub_pause (nullptr);
 
+  /* And undo here. */
+
   /* The spec includes 'cswh'.  Earlier versions of Windows
    * used to enable this by default, but testing suggests
    * that Windows 8 and later do not enable it by default,
@@ -235,23 +235,21 @@
    * Note that IranNastaliq uses this feature extensively
    * to fixup broken glyph sequences.  Oh well...
    * Test case: U+0643,U+0640,U+0631. */
-  //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
-  map->add_global_bool_feature (HB_TAG('m','s','e','t'));
+  //map->enable_feature (HB_TAG('c','s','w','h'));
+  map->enable_feature (HB_TAG('m','s','e','t'));
 }
 
 #include "hb-ot-shape-complex-arabic-fallback.hh"
 
 struct arabic_shape_plan_t
 {
-  ASSERT_POD ();
-
   /* The "+ 1" in the next array is to accommodate for the "NONE" command,
    * which is not an OpenType feature, but this simplifies the code by not
    * having to do a "if (... < NONE) ..." and just rely on the fact that
    * mask_array[NONE] == 0. */
   hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
 
-  arabic_fallback_plan_t *fallback_plan;
+  hb_atomic_ptr_t<arabic_fallback_plan_t> fallback_plan;
 
   unsigned int do_fallback : 1;
   unsigned int has_stch : 1;
@@ -380,19 +378,6 @@
   setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
 }
 
-
-static void
-nuke_joiners (const hb_ot_shape_plan_t *plan HB_UNUSED,
-              hb_font_t *font HB_UNUSED,
-              hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 0; i < count; i++)
-    if (_hb_glyph_info_is_zwj (&info[i]))
-      _hb_glyph_info_flip_joiners (&info[i]);
-}
-
 static void
 arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
                        hb_font_t *font,
@@ -404,12 +389,13 @@
     return;
 
 retry:
-  arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_atomic_ptr_get (&arabic_plan->fallback_plan);
+  arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
   if (unlikely (!fallback_plan))
   {
     /* This sucks.  We need a font to build the fallback plan... */
     fallback_plan = arabic_fallback_plan_create (plan, font);
-    if (unlikely (!hb_atomic_ptr_cmpexch (&(const_cast<arabic_shape_plan_t *> (arabic_plan))->fallback_plan, nullptr, fallback_plan))) {
+    if (unlikely (!arabic_plan->fallback_plan.cmpexch (nullptr, fallback_plan)))
+    {
       arabic_fallback_plan_destroy (fallback_plan);
       goto retry;
     }
@@ -428,7 +414,7 @@
 
 static void
 record_stch (const hb_ot_shape_plan_t *plan,
-             hb_font_t *font,
+             hb_font_t *font HB_UNUSED,
              hb_buffer_t *buffer)
 {
   const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
@@ -452,7 +438,7 @@
 }
 
 static void
-apply_stch (const hb_ot_shape_plan_t *plan,
+apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
             hb_buffer_t              *buffer,
             hb_font_t                *font)
 {
@@ -470,9 +456,9 @@
 
   int sign = font->x_scale < 0 ? -1 : +1;
   unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
-  typedef enum { MEASURE, CUT } step_t;
+  enum { MEASURE, CUT } /* step_t */;
 
-  for (step_t step = MEASURE; step <= CUT; step = (step_t) (step + 1))
+  for (unsigned int step = MEASURE; step <= CUT; step = step + 1)
   {
     unsigned int count = buffer->len;
     hb_glyph_info_t *info = buffer->info;
@@ -611,7 +597,7 @@
   HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
 }
 
-/* https://unicode.org/reports/tr53/tr53-1.pdf */
+/* http://www.unicode.org/reports/tr53/ */
 
 static hb_codepoint_t
 modifier_combining_marks[] =
@@ -623,6 +609,7 @@
   0x06E3u, /* ARABIC SMALL LOW SEEN */
   0x06E7u, /* ARABIC SMALL HIGH YEH */
   0x06E8u, /* ARABIC SMALL HIGH NOON */
+  0x08D3u, /* ARABIC SMALL LOW WAW */
   0x08F3u, /* ARABIC SMALL HIGH WAW */
 };
 
@@ -637,7 +624,7 @@
 }
 
 static void
-reorder_marks_arabic (const hb_ot_shape_plan_t *plan,
+reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
                       hb_buffer_t              *buffer,
                       unsigned int              start,
                       unsigned int              end)
@@ -714,7 +701,7 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   setup_masks_arabic,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   reorder_marks_arabic,
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-arabic.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2015  Mozilla Foundation.
+ * Copyright © 2015  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_HH
+#define HB_OT_SHAPE_COMPLEX_ARABIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+
+struct arabic_shape_plan_t;
+
+HB_INTERNAL void *
+data_create_arabic (const hb_ot_shape_plan_t *plan);
+
+HB_INTERNAL void
+data_destroy_arabic (void *data);
+
+HB_INTERNAL void
+setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
+                         hb_buffer_t               *buffer,
+                         hb_script_t                script);
+
+#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-default.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-default.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
@@ -39,7 +39,7 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hangul.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hangul.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 /* Hangul shaper */
@@ -56,7 +56,7 @@
   hb_ot_map_builder_t *map = &plan->map;
 
   for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
-    map->add_feature (hangul_features[i], 1, F_NONE);
+    map->add_feature (hangul_features[i]);
 }
 
 static void
@@ -65,13 +65,11 @@
   /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
    * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
    * in calt, which is not desirable. */
-  plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('c','a','l','t'));
 }
 
 struct hangul_shape_plan_t
 {
-  ASSERT_POD ();
-
   hb_mask_t mask_array[HANGUL_FEATURE_COUNT];
 };
 
@@ -128,7 +126,7 @@
 }
 
 static void
-preprocess_text_hangul (const hb_ot_shape_plan_t *plan,
+preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
                         hb_buffer_t              *buffer,
                         hb_font_t                *font)
 {
@@ -345,13 +343,6 @@
         {
           unsigned int s_len = tindex ? 3 : 2;
           buffer->replace_glyphs (1, s_len, decomposed);
-          if (unlikely (!buffer->successful))
-            return;
-
-          /* We decomposed S: apply jamo features to the individual glyphs
-           * that are now in buffer->out_info.
-           */
-          hb_glyph_info_t *info = buffer->out_info;
 
           /* If we decomposed an LV because of a non-combining T following,
            * we want to include this T in the syllable.
@@ -361,6 +352,14 @@
             buffer->next_glyph ();
             s_len++;
           }
+
+          if (unlikely (!buffer->successful))
+            return;
+
+          /* We decomposed S: apply jamo features to the individual glyphs
+           * that are now in buffer->out_info.
+           */
+          hb_glyph_info_t *info = buffer->out_info;
           end = start + s_len;
 
           unsigned int i = start;
@@ -368,6 +367,7 @@
           info[i++].hangul_shaping_feature() = VJMO;
           if (i < end)
             info[i++].hangul_shaping_feature() = TJMO;
+
           if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
             buffer->merge_out_clusters (start, end);
           continue;
@@ -424,7 +424,7 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   setup_masks_hangul,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hebrew.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-hebrew.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 static bool
@@ -70,7 +70,7 @@
 
   bool found = (bool) c->unicode->compose (a, b, ab);
 
-  if (!found && !c->plan->has_mark)
+  if (!found && !c->plan->has_gpos_mark)
   {
       /* Special-case Hebrew presentation forms that are excluded from
        * standard normalization, but wanted for old fonts. */
@@ -154,18 +154,6 @@
   return found;
 }
 
-static bool
-disable_otl_hebrew (const hb_ot_shape_plan_t *plan)
-{
-  /* For Hebrew shaper, use fallback if GPOS does not have 'hebr'
-   * script.  This matches Uniscribe better, and makes fonts like
-   * Arial that have GSUB/GPOS/GDEF but no data for Hebrew work.
-   * See:
-   * https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368
-   */
-  return plan->map.chosen_script[1] != HB_TAG ('h','e','b','r');
-}
-
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
 {
@@ -179,7 +167,7 @@
   nullptr, /* decompose */
   compose_hebrew,
   nullptr, /* setup_masks */
-  disable_otl_hebrew,
+  HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   true, /* fallback_position */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-machine.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-machine.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,892 +29,714 @@
 #ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-indic-machine.hh"
 static const unsigned char _indic_syllable_machine_trans_keys[] = {
-        8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
-        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u,
-        4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u,
-        16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u,
-        4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
-        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u,
-        4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u,
-        16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u,
-        4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 8u,
-        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u,
-        5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u,
-        16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
-        4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u,
-        8u, 8u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
+        8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
         5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u,
         4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u,
-        16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u,
-        4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, 5u, 8u, 5u, 8u, 5u, 7u, 5u, 8u,
-        5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u,
-        8u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
-        6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 8u, 8u, 1u, 19u, 3u, 17u,
-        3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u,
-        3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u,
-        3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u,
-        5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
-        3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u,
-        3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u,
-        1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u,
-        1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u,
-        3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u,
-        4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u,
-        4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u,
-        10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
+        16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u,
+        4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u,
+        7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u,
+        6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u,
+        4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u,
+        4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u,
+        5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u,
+        7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
+        6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u,
+        4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 8u, 8u, 4u, 8u, 5u, 7u,
+        7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u,
+        5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u,
+        4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u,
+        4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u,
+        5u, 8u, 8u, 8u, 1u, 19u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u,
+        3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u,
+        3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u,
+        5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u,
+        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
+        3u, 10u, 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u,
+        3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u,
+        1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u,
+        3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u,
+        3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u,
+        3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u,
+        10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u,
+        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 10u,
+        3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u,
+        1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u,
+        1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 10u, 3u, 10u, 4u, 10u, 1u, 16u,
+        3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u,
+        3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u,
+        5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u,
         3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u,
-        5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u,
-        1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u,
-        3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u,
-        1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
-        3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
-        3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u,
-        5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u,
-        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
-        3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u,
-        1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u,
-        1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u,
-        3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u, 3u, 17u, 4u, 8u,
-        3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
-        3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
-        3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u,
-        10u, 10u, 5u, 10u, 3u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u,
+        5u, 10u, 3u, 10u, 4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u,
+        3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u,
+        1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 13u,
+        3u, 10u, 4u, 8u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u,
+        4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u,
+        4u, 10u, 1u, 16u, 3u, 13u, 3u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 5u, 10u,
+        10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u,
         5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u,
-        4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u,
-        3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u,
-        1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u,
-        1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u,
-        10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u,
-        4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u,
+        4u, 10u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u,
+        1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u,
+        3u, 10u, 3u, 13u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 1u, 16u, 3u, 13u,
+        1u, 16u, 4u, 13u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u,
         3u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u,
         0
 };
 
 static const char _indic_syllable_machine_key_spans[] = {
-        1, 4, 3, 1, 4, 3, 1, 4,
-        3, 1, 4, 3, 1, 5, 1, 1,
-        5, 1, 1, 5, 1, 1, 5, 1,
-        1, 5, 10, 5, 10, 5, 10, 5,
-        10, 5, 10, 1, 4, 3, 1, 4,
-        3, 1, 4, 3, 1, 4, 3, 1,
-        5, 1, 1, 5, 1, 1, 5, 1,
-        1, 5, 1, 1, 5, 10, 5, 10,
-        5, 10, 5, 10, 5, 10, 1, 4,
-        3, 1, 4, 3, 1, 4, 3, 1,
-        4, 3, 1, 5, 1, 1, 5, 1,
-        1, 5, 1, 1, 5, 1, 1, 5,
-        10, 5, 10, 5, 10, 5, 10, 5,
-        1, 4, 3, 1, 4, 3, 1, 4,
+        1, 5, 3, 1, 4, 3, 1, 4,
         3, 1, 4, 3, 1, 5, 1, 1,
         5, 1, 1, 5, 1, 1, 5, 1,
-        1, 5, 10, 5, 10, 5, 10, 5,
-        10, 5, 10, 10, 4, 4, 3, 4,
-        3, 1, 4, 3, 1, 4, 3, 1,
+        1, 10, 5, 10, 5, 10, 5, 10,
+        5, 10, 1, 5, 3, 1, 4, 3,
+        1, 4, 3, 1, 4, 3, 1, 5,
+        1, 1, 5, 1, 1, 5, 1, 1,
+        5, 1, 1, 10, 5, 10, 5, 10,
+        5, 10, 5, 10, 1, 5, 3, 1,
+        4, 3, 1, 4, 3, 1, 4, 3,
         1, 5, 1, 1, 5, 1, 1, 5,
-        1, 1, 5, 1, 1, 1, 19, 15,
-        15, 14, 16, 15, 15, 14, 16, 15,
-        15, 14, 16, 15, 15, 14, 16, 15,
-        15, 14, 6, 6, 6, 1, 1, 1,
-        6, 8, 8, 7, 6, 8, 7, 6,
-        8, 7, 6, 8, 7, 6, 8, 7,
-        15, 15, 16, 16, 16, 16, 15, 15,
-        16, 16, 16, 16, 15, 15, 16, 16,
-        16, 16, 15, 15, 16, 16, 16, 16,
-        15, 15, 15, 15, 14, 16, 15, 15,
-        14, 16, 15, 15, 14, 16, 15, 15,
-        14, 16, 15, 15, 14, 6, 6, 6,
-        1, 1, 1, 6, 8, 8, 7, 6,
+        1, 1, 5, 1, 1, 10, 5, 10,
+        5, 10, 5, 10, 5, 1, 5, 3,
+        1, 4, 3, 1, 4, 3, 1, 4,
+        3, 1, 5, 1, 1, 5, 1, 1,
+        5, 1, 1, 5, 1, 1, 10, 5,
+        10, 5, 10, 5, 10, 5, 10, 10,
+        4, 1, 19, 11, 8, 7, 16, 11,
+        8, 7, 16, 11, 8, 7, 16, 11,
+        8, 7, 16, 11, 8, 7, 6, 6,
+        6, 1, 1, 1, 6, 8, 6, 8,
+        7, 6, 8, 7, 6, 8, 7, 6,
+        8, 7, 8, 11, 16, 16, 16, 8,
+        11, 16, 16, 16, 8, 11, 16, 16,
+        16, 8, 11, 16, 16, 16, 8, 11,
+        11, 8, 7, 16, 11, 8, 7, 16,
+        11, 8, 7, 16, 11, 8, 7, 16,
+        11, 8, 7, 6, 6, 6, 1, 1,
+        1, 6, 8, 6, 8, 7, 6, 8,
+        7, 6, 8, 7, 6, 8, 7, 8,
+        11, 16, 16, 16, 8, 11, 16, 16,
+        16, 8, 11, 16, 16, 16, 8, 11,
+        16, 16, 16, 5, 8, 8, 7, 16,
+        11, 8, 7, 16, 11, 8, 7, 16,
+        11, 8, 7, 16, 11, 8, 7, 6,
+        6, 6, 1, 1, 1, 6, 8, 6,
         8, 7, 6, 8, 7, 6, 8, 7,
-        6, 8, 7, 15, 15, 16, 16, 16,
-        16, 15, 15, 16, 16, 16, 16, 15,
-        15, 16, 16, 16, 16, 15, 15, 16,
-        16, 16, 16, 5, 15, 15, 14, 16,
-        15, 15, 14, 16, 15, 15, 14, 16,
-        15, 15, 14, 16, 15, 15, 14, 6,
-        6, 6, 1, 1, 1, 6, 8, 8,
-        7, 6, 8, 7, 6, 8, 7, 6,
-        8, 7, 6, 8, 7, 15, 15, 16,
-        16, 16, 16, 15, 15, 16, 16, 16,
-        16, 15, 15, 16, 16, 16, 16, 15,
-        15, 16, 16, 16, 16, 10, 15, 5,
-        15, 15, 14, 16, 15, 15, 14, 16,
-        15, 15, 14, 16, 15, 15, 14, 16,
-        15, 15, 14, 6, 6, 6, 1, 1,
-        1, 6, 8, 8, 7, 6, 8, 7,
+        6, 8, 7, 8, 11, 16, 16, 16,
+        8, 11, 16, 16, 16, 8, 11, 16,
+        16, 16, 8, 11, 16, 16, 16, 10,
+        8, 5, 11, 8, 7, 16, 11, 8,
+        7, 16, 11, 8, 7, 16, 11, 8,
+        7, 16, 11, 8, 7, 6, 6, 6,
+        1, 1, 1, 6, 8, 6, 8, 7,
         6, 8, 7, 6, 8, 7, 6, 8,
-        7, 15, 15, 16, 16, 16, 16, 15,
-        15, 16, 16, 16, 16, 15, 15, 16,
-        16, 16, 16, 15, 15, 16, 16, 16,
-        16, 15, 17, 15, 17, 10, 6, 1,
-        1, 1, 6, 16, 8, 7, 6, 8,
-        7, 6, 8, 7, 6, 8, 7, 6,
+        7, 8, 11, 16, 16, 16, 8, 11,
+        16, 16, 16, 8, 11, 16, 16, 16,
+        8, 11, 16, 16, 16, 8, 16, 11,
+        16, 10, 6, 1, 1, 1, 6, 16,
         8, 6, 6, 1, 1, 1, 6, 16
 };
 
 static const short _indic_syllable_machine_index_offsets[] = {
-        0, 2, 7, 11, 13, 18, 22, 24,
-        29, 33, 35, 40, 44, 46, 52, 54,
-        56, 62, 64, 66, 72, 74, 76, 82,
-        84, 86, 92, 103, 109, 120, 126, 137,
-        143, 154, 160, 171, 173, 178, 182, 184,
-        189, 193, 195, 200, 204, 206, 211, 215,
-        217, 223, 225, 227, 233, 235, 237, 243,
-        245, 247, 253, 255, 257, 263, 274, 280,
-        291, 297, 308, 314, 325, 331, 342, 344,
-        349, 353, 355, 360, 364, 366, 371, 375,
-        377, 382, 386, 388, 394, 396, 398, 404,
-        406, 408, 414, 416, 418, 424, 426, 428,
-        434, 445, 451, 462, 468, 479, 485, 496,
-        502, 504, 509, 513, 515, 520, 524, 526,
-        531, 535, 537, 542, 546, 548, 554, 556,
-        558, 564, 566, 568, 574, 576, 578, 584,
-        586, 588, 594, 605, 611, 622, 628, 639,
-        645, 656, 662, 673, 684, 689, 694, 698,
-        703, 707, 709, 714, 718, 720, 725, 729,
-        731, 733, 739, 741, 743, 749, 751, 753,
-        759, 761, 763, 769, 771, 773, 775, 795,
-        811, 827, 842, 859, 875, 891, 906, 923,
-        939, 955, 970, 987, 1003, 1019, 1034, 1051,
-        1067, 1083, 1098, 1105, 1112, 1119, 1121, 1123,
-        1125, 1132, 1141, 1150, 1158, 1165, 1174, 1182,
-        1189, 1198, 1206, 1213, 1222, 1230, 1237, 1246,
-        1254, 1270, 1286, 1303, 1320, 1337, 1354, 1370,
-        1386, 1403, 1420, 1437, 1454, 1470, 1486, 1503,
-        1520, 1537, 1554, 1570, 1586, 1603, 1620, 1637,
-        1654, 1670, 1686, 1702, 1718, 1733, 1750, 1766,
-        1782, 1797, 1814, 1830, 1846, 1861, 1878, 1894,
-        1910, 1925, 1942, 1958, 1974, 1989, 1996, 2003,
-        2010, 2012, 2014, 2016, 2023, 2032, 2041, 2049,
-        2056, 2065, 2073, 2080, 2089, 2097, 2104, 2113,
-        2121, 2128, 2137, 2145, 2161, 2177, 2194, 2211,
-        2228, 2245, 2261, 2277, 2294, 2311, 2328, 2345,
-        2361, 2377, 2394, 2411, 2428, 2445, 2461, 2477,
-        2494, 2511, 2528, 2545, 2551, 2567, 2583, 2598,
-        2615, 2631, 2647, 2662, 2679, 2695, 2711, 2726,
-        2743, 2759, 2775, 2790, 2807, 2823, 2839, 2854,
-        2861, 2868, 2875, 2877, 2879, 2881, 2888, 2897,
-        2906, 2914, 2921, 2930, 2938, 2945, 2954, 2962,
-        2969, 2978, 2986, 2993, 3002, 3010, 3026, 3042,
-        3059, 3076, 3093, 3110, 3126, 3142, 3159, 3176,
-        3193, 3210, 3226, 3242, 3259, 3276, 3293, 3310,
-        3326, 3342, 3359, 3376, 3393, 3410, 3421, 3437,
-        3443, 3459, 3475, 3490, 3507, 3523, 3539, 3554,
-        3571, 3587, 3603, 3618, 3635, 3651, 3667, 3682,
-        3699, 3715, 3731, 3746, 3753, 3760, 3767, 3769,
-        3771, 3773, 3780, 3789, 3798, 3806, 3813, 3822,
-        3830, 3837, 3846, 3854, 3861, 3870, 3878, 3885,
-        3894, 3902, 3918, 3934, 3951, 3968, 3985, 4002,
-        4018, 4034, 4051, 4068, 4085, 4102, 4118, 4134,
-        4151, 4168, 4185, 4202, 4218, 4234, 4251, 4268,
-        4285, 4302, 4318, 4336, 4352, 4370, 4381, 4388,
-        4390, 4392, 4394, 4401, 4418, 4427, 4435, 4442,
-        4451, 4459, 4466, 4475, 4483, 4490, 4499, 4507,
-        4514, 4523, 4530, 4537, 4539, 4541, 4543, 4550
+        0, 2, 8, 12, 14, 19, 23, 25,
+        30, 34, 36, 41, 45, 47, 53, 55,
+        57, 63, 65, 67, 73, 75, 77, 83,
+        85, 87, 98, 104, 115, 121, 132, 138,
+        149, 155, 166, 168, 174, 178, 180, 185,
+        189, 191, 196, 200, 202, 207, 211, 213,
+        219, 221, 223, 229, 231, 233, 239, 241,
+        243, 249, 251, 253, 264, 270, 281, 287,
+        298, 304, 315, 321, 332, 334, 340, 344,
+        346, 351, 355, 357, 362, 366, 368, 373,
+        377, 379, 385, 387, 389, 395, 397, 399,
+        405, 407, 409, 415, 417, 419, 430, 436,
+        447, 453, 464, 470, 481, 487, 489, 495,
+        499, 501, 506, 510, 512, 517, 521, 523,
+        528, 532, 534, 540, 542, 544, 550, 552,
+        554, 560, 562, 564, 570, 572, 574, 585,
+        591, 602, 608, 619, 625, 636, 642, 653,
+        664, 669, 671, 691, 703, 712, 720, 737,
+        749, 758, 766, 783, 795, 804, 812, 829,
+        841, 850, 858, 875, 887, 896, 904, 911,
+        918, 925, 927, 929, 931, 938, 947, 954,
+        963, 971, 978, 987, 995, 1002, 1011, 1019,
+        1026, 1035, 1043, 1052, 1064, 1081, 1098, 1115,
+        1124, 1136, 1153, 1170, 1187, 1196, 1208, 1225,
+        1242, 1259, 1268, 1280, 1297, 1314, 1331, 1340,
+        1352, 1364, 1373, 1381, 1398, 1410, 1419, 1427,
+        1444, 1456, 1465, 1473, 1490, 1502, 1511, 1519,
+        1536, 1548, 1557, 1565, 1572, 1579, 1586, 1588,
+        1590, 1592, 1599, 1608, 1615, 1624, 1632, 1639,
+        1648, 1656, 1663, 1672, 1680, 1687, 1696, 1704,
+        1713, 1725, 1742, 1759, 1776, 1785, 1797, 1814,
+        1831, 1848, 1857, 1869, 1886, 1903, 1920, 1929,
+        1941, 1958, 1975, 1992, 1998, 2007, 2016, 2024,
+        2041, 2053, 2062, 2070, 2087, 2099, 2108, 2116,
+        2133, 2145, 2154, 2162, 2179, 2191, 2200, 2208,
+        2215, 2222, 2229, 2231, 2233, 2235, 2242, 2251,
+        2258, 2267, 2275, 2282, 2291, 2299, 2306, 2315,
+        2323, 2330, 2339, 2347, 2356, 2368, 2385, 2402,
+        2419, 2428, 2440, 2457, 2474, 2491, 2500, 2512,
+        2529, 2546, 2563, 2572, 2584, 2601, 2618, 2635,
+        2646, 2655, 2661, 2673, 2682, 2690, 2707, 2719,
+        2728, 2736, 2753, 2765, 2774, 2782, 2799, 2811,
+        2820, 2828, 2845, 2857, 2866, 2874, 2881, 2888,
+        2895, 2897, 2899, 2901, 2908, 2917, 2924, 2933,
+        2941, 2948, 2957, 2965, 2972, 2981, 2989, 2996,
+        3005, 3013, 3022, 3034, 3051, 3068, 3085, 3094,
+        3106, 3123, 3140, 3157, 3166, 3178, 3195, 3212,
+        3229, 3238, 3250, 3267, 3284, 3301, 3310, 3327,
+        3339, 3356, 3367, 3374, 3376, 3378, 3380, 3387,
+        3404, 3413, 3420, 3427, 3429, 3431, 3433, 3440
 };
 
 static const short _indic_syllable_machine_indicies[] = {
-        1, 0, 2, 2, 3, 1, 0, 4,
-        4, 3, 0, 3, 0, 5, 5, 6,
-        1, 0, 7, 7, 6, 0, 6, 0,
-        8, 8, 9, 1, 0, 10, 10, 9,
-        0, 9, 0, 11, 11, 12, 1, 0,
-        13, 13, 12, 0, 12, 0, 14, 0,
-        0, 0, 1, 0, 15, 0, 16, 0,
-        17, 11, 11, 12, 1, 0, 18, 0,
-        19, 0, 20, 8, 8, 9, 1, 0,
-        21, 0, 22, 0, 23, 5, 5, 6,
-        1, 0, 24, 0, 25, 0, 26, 2,
-        2, 3, 1, 0, 26, 2, 2, 3,
-        1, 0, 0, 0, 0, 27, 0, 28,
-        2, 2, 3, 1, 0, 28, 2, 2,
-        3, 1, 0, 0, 0, 0, 29, 0,
-        30, 2, 2, 3, 1, 0, 30, 2,
-        2, 3, 1, 0, 0, 0, 0, 31,
-        0, 32, 2, 2, 3, 1, 0, 32,
-        2, 2, 3, 1, 0, 0, 0, 0,
-        33, 0, 34, 2, 2, 3, 1, 0,
-        34, 2, 2, 3, 1, 0, 0, 0,
-        0, 35, 0, 37, 36, 38, 38, 39,
-        37, 36, 40, 40, 39, 36, 39, 36,
-        41, 41, 42, 37, 36, 43, 43, 42,
-        36, 42, 36, 44, 44, 45, 37, 36,
-        46, 46, 45, 36, 45, 36, 47, 47,
-        48, 37, 36, 49, 49, 48, 36, 48,
-        36, 50, 36, 36, 36, 37, 36, 51,
-        36, 52, 36, 53, 47, 47, 48, 37,
-        36, 54, 36, 55, 36, 56, 44, 44,
-        45, 37, 36, 57, 36, 58, 36, 59,
-        41, 41, 42, 37, 36, 60, 36, 61,
-        36, 62, 38, 38, 39, 37, 36, 62,
-        38, 38, 39, 37, 36, 36, 36, 36,
-        63, 36, 64, 38, 38, 39, 37, 36,
-        64, 38, 38, 39, 37, 36, 36, 36,
-        36, 65, 36, 66, 38, 38, 39, 37,
-        36, 66, 38, 38, 39, 37, 36, 36,
-        36, 36, 67, 36, 68, 38, 38, 39,
-        37, 36, 68, 38, 38, 39, 37, 36,
-        36, 36, 36, 69, 36, 70, 38, 38,
-        39, 37, 36, 70, 38, 38, 39, 37,
-        36, 36, 36, 36, 71, 36, 73, 72,
-        74, 74, 75, 73, 72, 77, 77, 75,
-        76, 75, 76, 78, 78, 79, 73, 72,
-        80, 80, 79, 72, 79, 72, 81, 81,
-        82, 73, 72, 83, 83, 82, 72, 82,
-        72, 84, 84, 85, 73, 72, 86, 86,
-        85, 72, 85, 72, 87, 72, 72, 72,
-        73, 72, 88, 72, 89, 72, 90, 84,
-        84, 85, 73, 72, 91, 72, 92, 72,
-        93, 81, 81, 82, 73, 72, 94, 72,
-        95, 72, 96, 78, 78, 79, 73, 72,
-        97, 72, 98, 72, 99, 74, 74, 75,
-        73, 72, 99, 74, 74, 75, 73, 72,
-        72, 72, 72, 100, 72, 101, 74, 74,
-        75, 73, 72, 101, 74, 74, 75, 73,
-        72, 72, 72, 72, 102, 72, 103, 74,
-        74, 75, 73, 72, 103, 74, 74, 75,
-        73, 72, 72, 72, 72, 104, 72, 105,
-        74, 74, 75, 73, 72, 105, 74, 74,
-        75, 73, 72, 72, 72, 72, 106, 72,
-        107, 74, 74, 75, 73, 72, 109, 108,
-        110, 110, 111, 109, 108, 112, 112, 111,
-        108, 111, 108, 113, 113, 114, 109, 108,
-        115, 115, 114, 108, 114, 108, 116, 116,
-        117, 109, 108, 118, 118, 117, 108, 117,
-        108, 119, 119, 120, 109, 108, 121, 121,
-        120, 108, 120, 108, 122, 108, 108, 108,
-        109, 108, 123, 108, 124, 108, 125, 119,
-        119, 120, 109, 108, 126, 108, 127, 108,
-        128, 116, 116, 117, 109, 108, 129, 108,
-        130, 108, 131, 113, 113, 114, 109, 108,
-        132, 108, 133, 108, 134, 110, 110, 111,
-        109, 108, 134, 110, 110, 111, 109, 108,
-        108, 108, 108, 135, 108, 136, 110, 110,
-        111, 109, 108, 136, 110, 110, 111, 109,
-        108, 108, 108, 108, 137, 108, 138, 110,
-        110, 111, 109, 108, 138, 110, 110, 111,
-        109, 108, 108, 108, 108, 139, 108, 140,
-        110, 110, 111, 109, 108, 140, 110, 110,
-        111, 109, 108, 108, 108, 108, 141, 108,
-        142, 110, 110, 111, 109, 108, 142, 110,
-        110, 111, 109, 108, 108, 108, 108, 143,
-        108, 107, 74, 74, 75, 73, 72, 72,
-        72, 72, 144, 72, 77, 77, 75, 1,
-        0, 145, 145, 146, 1, 0, 4, 4,
-        146, 0, 147, 147, 148, 149, 0, 150,
-        150, 148, 0, 148, 0, 151, 151, 152,
-        149, 0, 153, 153, 152, 0, 152, 0,
-        154, 154, 155, 149, 0, 156, 156, 155,
-        0, 155, 0, 149, 0, 157, 0, 0,
-        0, 149, 0, 158, 0, 159, 0, 160,
-        154, 154, 155, 149, 0, 161, 0, 162,
-        0, 163, 151, 151, 152, 149, 0, 164,
-        0, 165, 0, 166, 147, 147, 148, 149,
-        0, 167, 0, 168, 0, 170, 169, 172,
-        173, 174, 175, 176, 177, 75, 73, 171,
-        178, 179, 179, 144, 171, 180, 181, 182,
-        183, 184, 171, 186, 187, 188, 189, 3,
-        1, 185, 190, 185, 185, 35, 185, 185,
-        185, 191, 185, 192, 187, 193, 193, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 187, 193, 193, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 194, 185, 185, 185, 16, 195,
-        185, 1, 185, 190, 185, 185, 185, 185,
-        185, 194, 185, 196, 197, 198, 199, 3,
-        1, 185, 190, 185, 185, 33, 185, 185,
-        185, 191, 185, 200, 197, 201, 201, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 197, 201, 201, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 202, 185, 185, 185, 16, 203,
-        185, 1, 185, 190, 185, 185, 185, 185,
-        185, 202, 185, 204, 205, 206, 207, 3,
-        1, 185, 190, 185, 185, 31, 185, 185,
-        185, 191, 185, 208, 205, 209, 209, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 205, 209, 209, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 210, 185, 185, 185, 16, 211,
-        185, 1, 185, 190, 185, 185, 185, 185,
-        185, 210, 185, 212, 213, 214, 215, 3,
-        1, 185, 190, 185, 185, 29, 185, 185,
-        185, 191, 185, 216, 213, 217, 217, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 213, 217, 217, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 218, 185, 185, 185, 16, 219,
-        185, 1, 185, 190, 185, 185, 185, 185,
-        185, 218, 185, 220, 221, 222, 223, 3,
-        1, 185, 190, 185, 185, 27, 185, 185,
-        185, 191, 185, 224, 221, 225, 225, 3,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        185, 191, 185, 221, 225, 225, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 16, 226, 185, 1, 185, 190,
-        185, 227, 227, 185, 1, 185, 190, 185,
-        228, 185, 185, 229, 185, 190, 185, 190,
-        185, 230, 185, 231, 185, 228, 185, 185,
-        185, 185, 190, 185, 16, 185, 232, 232,
-        3, 1, 185, 190, 185, 233, 25, 234,
-        235, 6, 1, 185, 190, 185, 25, 234,
-        235, 6, 1, 185, 190, 185, 234, 234,
-        6, 1, 185, 190, 185, 236, 22, 237,
-        238, 9, 1, 185, 190, 185, 22, 237,
-        238, 9, 1, 185, 190, 185, 237, 237,
-        9, 1, 185, 190, 185, 239, 19, 240,
-        241, 12, 1, 185, 190, 185, 19, 240,
-        241, 12, 1, 185, 190, 185, 240, 240,
-        12, 1, 185, 190, 185, 242, 16, 227,
-        243, 185, 1, 185, 190, 185, 16, 227,
-        243, 185, 1, 185, 190, 185, 227, 244,
-        185, 1, 185, 190, 185, 16, 185, 227,
-        227, 185, 1, 185, 190, 185, 221, 225,
-        225, 3, 1, 185, 190, 185, 220, 221,
-        225, 225, 3, 1, 185, 190, 185, 185,
-        185, 185, 185, 185, 191, 185, 220, 221,
-        222, 225, 3, 1, 185, 190, 185, 185,
-        27, 185, 185, 185, 191, 185, 218, 185,
-        245, 185, 232, 232, 3, 1, 185, 190,
-        185, 185, 185, 185, 185, 218, 185, 218,
-        185, 185, 185, 227, 227, 185, 1, 185,
-        190, 185, 185, 185, 185, 185, 218, 185,
-        218, 185, 185, 185, 227, 246, 185, 1,
-        185, 190, 185, 185, 185, 185, 185, 218,
-        185, 218, 185, 245, 185, 227, 227, 185,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        218, 185, 212, 213, 217, 217, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 212, 213, 214, 217, 3, 1,
-        185, 190, 185, 185, 29, 185, 185, 185,
-        191, 185, 210, 185, 247, 185, 232, 232,
-        3, 1, 185, 190, 185, 185, 185, 185,
-        185, 210, 185, 210, 185, 185, 185, 227,
-        227, 185, 1, 185, 190, 185, 185, 185,
-        185, 185, 210, 185, 210, 185, 185, 185,
-        227, 248, 185, 1, 185, 190, 185, 185,
-        185, 185, 185, 210, 185, 210, 185, 247,
-        185, 227, 227, 185, 1, 185, 190, 185,
-        185, 185, 185, 185, 210, 185, 204, 205,
-        209, 209, 3, 1, 185, 190, 185, 185,
-        185, 185, 185, 185, 191, 185, 204, 205,
-        206, 209, 3, 1, 185, 190, 185, 185,
-        31, 185, 185, 185, 191, 185, 202, 185,
-        249, 185, 232, 232, 3, 1, 185, 190,
-        185, 185, 185, 185, 185, 202, 185, 202,
-        185, 185, 185, 227, 227, 185, 1, 185,
-        190, 185, 185, 185, 185, 185, 202, 185,
-        202, 185, 185, 185, 227, 250, 185, 1,
-        185, 190, 185, 185, 185, 185, 185, 202,
-        185, 202, 185, 249, 185, 227, 227, 185,
-        1, 185, 190, 185, 185, 185, 185, 185,
-        202, 185, 196, 197, 201, 201, 3, 1,
-        185, 190, 185, 185, 185, 185, 185, 185,
-        191, 185, 196, 197, 198, 201, 3, 1,
-        185, 190, 185, 185, 33, 185, 185, 185,
-        191, 185, 194, 185, 251, 185, 232, 232,
-        3, 1, 185, 190, 185, 185, 185, 185,
-        185, 194, 185, 194, 185, 185, 185, 227,
-        227, 185, 1, 185, 190, 185, 185, 185,
-        185, 185, 194, 185, 194, 185, 185, 185,
-        227, 252, 185, 1, 185, 190, 185, 185,
-        185, 185, 185, 194, 185, 194, 185, 251,
-        185, 227, 227, 185, 1, 185, 190, 185,
-        185, 185, 185, 185, 194, 185, 186, 187,
-        193, 193, 3, 1, 185, 190, 185, 185,
-        185, 185, 185, 185, 191, 185, 186, 187,
-        188, 193, 3, 1, 185, 190, 185, 185,
-        35, 185, 185, 185, 191, 185, 254, 255,
-        256, 257, 39, 37, 253, 258, 253, 253,
-        71, 253, 253, 253, 259, 253, 260, 255,
-        261, 257, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 255, 261,
-        257, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 262, 253, 253,
-        253, 52, 263, 253, 37, 253, 258, 253,
-        253, 253, 253, 253, 262, 253, 264, 265,
-        266, 267, 39, 37, 253, 258, 253, 253,
-        69, 253, 253, 253, 259, 253, 268, 265,
-        269, 269, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 265, 269,
-        269, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 270, 253, 253,
-        253, 52, 271, 253, 37, 253, 258, 253,
-        253, 253, 253, 253, 270, 253, 272, 273,
-        274, 275, 39, 37, 253, 258, 253, 253,
-        67, 253, 253, 253, 259, 253, 276, 273,
-        277, 277, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 273, 277,
-        277, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 278, 253, 253,
-        253, 52, 279, 253, 37, 253, 258, 253,
-        253, 253, 253, 253, 278, 253, 280, 281,
-        282, 283, 39, 37, 253, 258, 253, 253,
-        65, 253, 253, 253, 259, 253, 284, 281,
-        285, 285, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 281, 285,
-        285, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 286, 253, 253,
-        253, 52, 287, 253, 37, 253, 258, 253,
-        253, 253, 253, 253, 286, 253, 288, 289,
-        290, 291, 39, 37, 253, 258, 253, 253,
-        63, 253, 253, 253, 259, 253, 292, 289,
-        293, 293, 39, 37, 253, 258, 253, 253,
-        253, 253, 253, 253, 259, 253, 289, 293,
-        293, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 52, 294, 253,
-        37, 253, 258, 253, 295, 295, 253, 37,
-        253, 258, 253, 296, 253, 253, 297, 253,
-        258, 253, 258, 253, 298, 253, 299, 253,
-        296, 253, 253, 253, 253, 258, 253, 52,
-        253, 300, 300, 39, 37, 253, 258, 253,
-        301, 61, 302, 303, 42, 37, 253, 258,
-        253, 61, 302, 303, 42, 37, 253, 258,
-        253, 302, 302, 42, 37, 253, 258, 253,
-        304, 58, 305, 306, 45, 37, 253, 258,
-        253, 58, 305, 306, 45, 37, 253, 258,
-        253, 305, 305, 45, 37, 253, 258, 253,
-        307, 55, 308, 309, 48, 37, 253, 258,
-        253, 55, 308, 309, 48, 37, 253, 258,
-        253, 308, 308, 48, 37, 253, 258, 253,
-        310, 52, 295, 311, 253, 37, 253, 258,
-        253, 52, 295, 311, 253, 37, 253, 258,
-        253, 295, 312, 253, 37, 253, 258, 253,
-        52, 253, 295, 295, 253, 37, 253, 258,
-        253, 289, 293, 293, 39, 37, 253, 258,
-        253, 288, 289, 293, 293, 39, 37, 253,
-        258, 253, 253, 253, 253, 253, 253, 259,
-        253, 288, 289, 290, 293, 39, 37, 253,
-        258, 253, 253, 63, 253, 253, 253, 259,
-        253, 286, 253, 313, 253, 300, 300, 39,
-        37, 253, 258, 253, 253, 253, 253, 253,
-        286, 253, 286, 253, 253, 253, 295, 295,
-        253, 37, 253, 258, 253, 253, 253, 253,
-        253, 286, 253, 286, 253, 253, 253, 295,
-        314, 253, 37, 253, 258, 253, 253, 253,
-        253, 253, 286, 253, 286, 253, 313, 253,
-        295, 295, 253, 37, 253, 258, 253, 253,
-        253, 253, 253, 286, 253, 280, 281, 285,
-        285, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 280, 281, 282,
-        285, 39, 37, 253, 258, 253, 253, 65,
-        253, 253, 253, 259, 253, 278, 253, 315,
-        253, 300, 300, 39, 37, 253, 258, 253,
-        253, 253, 253, 253, 278, 253, 278, 253,
-        253, 253, 295, 295, 253, 37, 253, 258,
-        253, 253, 253, 253, 253, 278, 253, 278,
-        253, 253, 253, 295, 316, 253, 37, 253,
-        258, 253, 253, 253, 253, 253, 278, 253,
-        278, 253, 315, 253, 295, 295, 253, 37,
-        253, 258, 253, 253, 253, 253, 253, 278,
-        253, 272, 273, 277, 277, 39, 37, 253,
-        258, 253, 253, 253, 253, 253, 253, 259,
-        253, 272, 273, 274, 277, 39, 37, 253,
-        258, 253, 253, 67, 253, 253, 253, 259,
-        253, 270, 253, 317, 253, 300, 300, 39,
-        37, 253, 258, 253, 253, 253, 253, 253,
-        270, 253, 270, 253, 253, 253, 295, 295,
-        253, 37, 253, 258, 253, 253, 253, 253,
-        253, 270, 253, 270, 253, 253, 253, 295,
-        318, 253, 37, 253, 258, 253, 253, 253,
-        253, 253, 270, 253, 270, 253, 317, 253,
-        295, 295, 253, 37, 253, 258, 253, 253,
-        253, 253, 253, 270, 253, 264, 265, 269,
-        269, 39, 37, 253, 258, 253, 253, 253,
-        253, 253, 253, 259, 253, 264, 265, 266,
-        269, 39, 37, 253, 258, 253, 253, 69,
-        253, 253, 253, 259, 253, 262, 253, 319,
-        253, 300, 300, 39, 37, 253, 258, 253,
-        253, 253, 253, 253, 262, 253, 262, 253,
-        253, 253, 295, 295, 253, 37, 253, 258,
-        253, 253, 253, 253, 253, 262, 253, 262,
-        253, 253, 253, 295, 320, 253, 37, 253,
-        258, 253, 253, 253, 253, 253, 262, 253,
-        262, 253, 319, 253, 295, 295, 253, 37,
-        253, 258, 253, 253, 253, 253, 253, 262,
-        253, 70, 38, 38, 39, 37, 253, 254,
-        255, 261, 257, 39, 37, 253, 258, 253,
-        253, 253, 253, 253, 253, 259, 253, 322,
-        175, 323, 323, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 175,
-        323, 323, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 324, 321,
-        321, 321, 89, 325, 321, 73, 321, 178,
-        321, 321, 321, 321, 321, 324, 321, 326,
-        327, 328, 329, 75, 73, 321, 178, 321,
-        321, 106, 321, 321, 321, 182, 321, 330,
-        327, 331, 331, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 327,
-        331, 331, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 332, 321,
-        321, 321, 89, 333, 321, 73, 321, 178,
-        321, 321, 321, 321, 321, 332, 321, 334,
-        335, 336, 337, 75, 73, 321, 178, 321,
-        321, 104, 321, 321, 321, 182, 321, 338,
-        335, 339, 339, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 335,
-        339, 339, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 340, 321,
-        321, 321, 89, 341, 321, 73, 321, 178,
-        321, 321, 321, 321, 321, 340, 321, 342,
-        343, 344, 345, 75, 73, 321, 178, 321,
-        321, 102, 321, 321, 321, 182, 321, 346,
-        343, 347, 347, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 343,
-        347, 347, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 348, 321,
-        321, 321, 89, 349, 321, 73, 321, 178,
-        321, 321, 321, 321, 321, 348, 321, 350,
-        351, 352, 353, 75, 73, 321, 178, 321,
-        321, 100, 321, 321, 321, 182, 321, 354,
-        351, 355, 355, 75, 73, 321, 178, 321,
-        321, 321, 321, 321, 321, 182, 321, 351,
-        355, 355, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 89, 356,
-        321, 73, 321, 178, 321, 357, 357, 321,
-        73, 321, 178, 321, 358, 321, 321, 359,
-        321, 178, 321, 178, 321, 360, 321, 361,
-        321, 358, 321, 321, 321, 321, 178, 321,
-        89, 321, 362, 362, 75, 73, 321, 178,
-        321, 363, 98, 364, 365, 79, 73, 321,
-        178, 321, 98, 364, 365, 79, 73, 321,
-        178, 321, 364, 364, 79, 73, 321, 178,
-        321, 366, 95, 367, 368, 82, 73, 321,
-        178, 321, 95, 367, 368, 82, 73, 321,
-        178, 321, 367, 367, 82, 73, 321, 178,
-        321, 369, 92, 370, 371, 85, 73, 321,
-        178, 321, 92, 370, 371, 85, 73, 321,
-        178, 321, 370, 370, 85, 73, 321, 178,
-        321, 372, 89, 357, 373, 321, 73, 321,
-        178, 321, 89, 357, 373, 321, 73, 321,
-        178, 321, 357, 374, 321, 73, 321, 178,
-        321, 89, 321, 357, 357, 321, 73, 321,
-        178, 321, 351, 355, 355, 75, 73, 321,
-        178, 321, 350, 351, 355, 355, 75, 73,
-        321, 178, 321, 321, 321, 321, 321, 321,
-        182, 321, 350, 351, 352, 355, 75, 73,
-        321, 178, 321, 321, 100, 321, 321, 321,
-        182, 321, 348, 321, 375, 321, 362, 362,
-        75, 73, 321, 178, 321, 321, 321, 321,
-        321, 348, 321, 348, 321, 321, 321, 357,
-        357, 321, 73, 321, 178, 321, 321, 321,
-        321, 321, 348, 321, 348, 321, 321, 321,
-        357, 376, 321, 73, 321, 178, 321, 321,
-        321, 321, 321, 348, 321, 348, 321, 375,
-        321, 357, 357, 321, 73, 321, 178, 321,
-        321, 321, 321, 321, 348, 321, 342, 343,
-        347, 347, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 342, 343,
-        344, 347, 75, 73, 321, 178, 321, 321,
-        102, 321, 321, 321, 182, 321, 340, 321,
-        377, 321, 362, 362, 75, 73, 321, 178,
-        321, 321, 321, 321, 321, 340, 321, 340,
-        321, 321, 321, 357, 357, 321, 73, 321,
-        178, 321, 321, 321, 321, 321, 340, 321,
-        340, 321, 321, 321, 357, 378, 321, 73,
-        321, 178, 321, 321, 321, 321, 321, 340,
-        321, 340, 321, 377, 321, 357, 357, 321,
-        73, 321, 178, 321, 321, 321, 321, 321,
-        340, 321, 334, 335, 339, 339, 75, 73,
-        321, 178, 321, 321, 321, 321, 321, 321,
-        182, 321, 334, 335, 336, 339, 75, 73,
-        321, 178, 321, 321, 104, 321, 321, 321,
-        182, 321, 332, 321, 379, 321, 362, 362,
-        75, 73, 321, 178, 321, 321, 321, 321,
-        321, 332, 321, 332, 321, 321, 321, 357,
-        357, 321, 73, 321, 178, 321, 321, 321,
-        321, 321, 332, 321, 332, 321, 321, 321,
-        357, 380, 321, 73, 321, 178, 321, 321,
-        321, 321, 321, 332, 321, 332, 321, 379,
-        321, 357, 357, 321, 73, 321, 178, 321,
-        321, 321, 321, 321, 332, 321, 326, 327,
-        331, 331, 75, 73, 321, 178, 321, 321,
-        321, 321, 321, 321, 182, 321, 326, 327,
-        328, 331, 75, 73, 321, 178, 321, 321,
-        106, 321, 321, 321, 182, 321, 324, 321,
-        381, 321, 362, 362, 75, 73, 321, 178,
-        321, 321, 321, 321, 321, 324, 321, 324,
-        321, 321, 321, 357, 357, 321, 73, 321,
-        178, 321, 321, 321, 321, 321, 324, 321,
-        324, 321, 321, 321, 357, 382, 321, 73,
-        321, 178, 321, 321, 321, 321, 321, 324,
-        321, 324, 321, 381, 321, 357, 357, 321,
-        73, 321, 178, 321, 321, 321, 321, 321,
-        324, 321, 107, 74, 74, 75, 73, 383,
-        383, 383, 383, 144, 383, 174, 175, 323,
-        323, 75, 73, 321, 178, 321, 321, 321,
-        321, 321, 321, 182, 321, 107, 74, 74,
-        75, 73, 383, 385, 386, 387, 388, 111,
-        109, 384, 389, 384, 384, 143, 384, 384,
-        384, 390, 384, 391, 386, 388, 388, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 386, 388, 388, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 392, 384, 384, 384, 124, 393,
-        384, 109, 384, 389, 384, 384, 384, 384,
-        384, 392, 384, 394, 395, 396, 397, 111,
-        109, 384, 389, 384, 384, 141, 384, 384,
-        384, 390, 384, 398, 395, 399, 399, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 395, 399, 399, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 400, 384, 384, 384, 124, 401,
-        384, 109, 384, 389, 384, 384, 384, 384,
-        384, 400, 384, 402, 403, 404, 405, 111,
-        109, 384, 389, 384, 384, 139, 384, 384,
-        384, 390, 384, 406, 403, 407, 407, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 403, 407, 407, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 408, 384, 384, 384, 124, 409,
-        384, 109, 384, 389, 384, 384, 384, 384,
-        384, 408, 384, 410, 411, 412, 413, 111,
-        109, 384, 389, 384, 384, 137, 384, 384,
-        384, 390, 384, 414, 411, 415, 415, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 411, 415, 415, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 416, 384, 384, 384, 124, 417,
-        384, 109, 384, 389, 384, 384, 384, 384,
-        384, 416, 384, 418, 419, 420, 421, 111,
-        109, 384, 389, 384, 384, 135, 384, 384,
-        384, 390, 384, 422, 419, 423, 423, 111,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        384, 390, 384, 419, 423, 423, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 124, 424, 384, 109, 384, 389,
-        384, 425, 425, 384, 109, 384, 389, 384,
-        426, 384, 384, 427, 384, 389, 384, 389,
-        384, 428, 384, 429, 384, 426, 384, 384,
-        384, 384, 389, 384, 124, 384, 430, 430,
-        111, 109, 384, 389, 384, 431, 133, 432,
-        433, 114, 109, 384, 389, 384, 133, 432,
-        433, 114, 109, 384, 389, 384, 432, 432,
-        114, 109, 384, 389, 384, 434, 130, 435,
-        436, 117, 109, 384, 389, 384, 130, 435,
-        436, 117, 109, 384, 389, 384, 435, 435,
-        117, 109, 384, 389, 384, 437, 127, 438,
-        439, 120, 109, 384, 389, 384, 127, 438,
-        439, 120, 109, 384, 389, 384, 438, 438,
-        120, 109, 384, 389, 384, 440, 124, 425,
-        441, 384, 109, 384, 389, 384, 124, 425,
-        441, 384, 109, 384, 389, 384, 425, 442,
-        384, 109, 384, 389, 384, 124, 384, 425,
-        425, 384, 109, 384, 389, 384, 419, 423,
-        423, 111, 109, 384, 389, 384, 418, 419,
-        423, 423, 111, 109, 384, 389, 384, 384,
-        384, 384, 384, 384, 390, 384, 418, 419,
-        420, 423, 111, 109, 384, 389, 384, 384,
-        135, 384, 384, 384, 390, 384, 416, 384,
-        443, 384, 430, 430, 111, 109, 384, 389,
-        384, 384, 384, 384, 384, 416, 384, 416,
-        384, 384, 384, 425, 425, 384, 109, 384,
-        389, 384, 384, 384, 384, 384, 416, 384,
-        416, 384, 384, 384, 425, 444, 384, 109,
-        384, 389, 384, 384, 384, 384, 384, 416,
-        384, 416, 384, 443, 384, 425, 425, 384,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        416, 384, 410, 411, 415, 415, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 410, 411, 412, 415, 111, 109,
-        384, 389, 384, 384, 137, 384, 384, 384,
-        390, 384, 408, 384, 445, 384, 430, 430,
-        111, 109, 384, 389, 384, 384, 384, 384,
-        384, 408, 384, 408, 384, 384, 384, 425,
-        425, 384, 109, 384, 389, 384, 384, 384,
-        384, 384, 408, 384, 408, 384, 384, 384,
-        425, 446, 384, 109, 384, 389, 384, 384,
-        384, 384, 384, 408, 384, 408, 384, 445,
-        384, 425, 425, 384, 109, 384, 389, 384,
-        384, 384, 384, 384, 408, 384, 402, 403,
-        407, 407, 111, 109, 384, 389, 384, 384,
-        384, 384, 384, 384, 390, 384, 402, 403,
-        404, 407, 111, 109, 384, 389, 384, 384,
-        139, 384, 384, 384, 390, 384, 400, 384,
-        447, 384, 430, 430, 111, 109, 384, 389,
-        384, 384, 384, 384, 384, 400, 384, 400,
-        384, 384, 384, 425, 425, 384, 109, 384,
-        389, 384, 384, 384, 384, 384, 400, 384,
-        400, 384, 384, 384, 425, 448, 384, 109,
-        384, 389, 384, 384, 384, 384, 384, 400,
-        384, 400, 384, 447, 384, 425, 425, 384,
-        109, 384, 389, 384, 384, 384, 384, 384,
-        400, 384, 394, 395, 399, 399, 111, 109,
-        384, 389, 384, 384, 384, 384, 384, 384,
-        390, 384, 394, 395, 396, 399, 111, 109,
-        384, 389, 384, 384, 141, 384, 384, 384,
-        390, 384, 392, 384, 449, 384, 430, 430,
-        111, 109, 384, 389, 384, 384, 384, 384,
-        384, 392, 384, 392, 384, 384, 384, 425,
-        425, 384, 109, 384, 389, 384, 384, 384,
-        384, 384, 392, 384, 392, 384, 384, 384,
-        425, 450, 384, 109, 384, 389, 384, 384,
-        384, 384, 384, 392, 384, 392, 384, 449,
-        384, 425, 425, 384, 109, 384, 389, 384,
-        384, 384, 384, 384, 392, 384, 385, 386,
-        388, 388, 111, 109, 384, 389, 384, 384,
-        384, 384, 384, 384, 390, 384, 172, 173,
-        174, 175, 451, 323, 75, 73, 321, 178,
-        179, 179, 144, 321, 321, 172, 182, 321,
-        186, 452, 188, 189, 3, 1, 185, 190,
-        185, 185, 35, 185, 185, 185, 191, 185,
-        194, 173, 174, 175, 453, 454, 75, 149,
-        185, 455, 185, 179, 144, 185, 185, 194,
-        182, 185, 107, 456, 456, 75, 149, 185,
-        190, 185, 185, 144, 185, 457, 185, 185,
-        458, 185, 455, 185, 455, 185, 459, 185,
-        231, 185, 457, 185, 185, 185, 185, 455,
-        185, 194, 185, 251, 107, 460, 460, 146,
-        149, 185, 190, 185, 185, 185, 185, 185,
-        194, 185, 461, 168, 462, 463, 148, 149,
-        185, 455, 185, 168, 462, 463, 148, 149,
-        185, 455, 185, 462, 462, 148, 149, 185,
-        455, 185, 464, 165, 465, 466, 152, 149,
-        185, 455, 185, 165, 465, 466, 152, 149,
-        185, 455, 185, 465, 465, 152, 149, 185,
-        455, 185, 467, 162, 468, 469, 155, 149,
-        185, 455, 185, 162, 468, 469, 155, 149,
-        185, 455, 185, 468, 468, 155, 149, 185,
-        455, 185, 470, 159, 471, 472, 185, 149,
-        185, 455, 185, 159, 471, 472, 185, 149,
-        185, 455, 185, 471, 471, 185, 149, 185,
-        455, 185, 474, 473, 475, 475, 473, 170,
-        473, 476, 473, 475, 475, 473, 170, 473,
-        476, 473, 477, 473, 473, 478, 473, 476,
-        473, 476, 473, 479, 473, 480, 473, 477,
-        473, 473, 473, 473, 476, 473, 172, 383,
-        383, 383, 383, 383, 383, 383, 383, 383,
-        179, 383, 383, 383, 383, 172, 383, 0
+        1, 0, 2, 3, 3, 4, 1, 0,
+        5, 5, 4, 0, 4, 0, 6, 6,
+        7, 1, 0, 8, 8, 7, 0, 7,
+        0, 9, 9, 10, 1, 0, 11, 11,
+        10, 0, 10, 0, 12, 12, 13, 1,
+        0, 14, 14, 13, 0, 13, 0, 15,
+        0, 0, 0, 1, 0, 16, 0, 17,
+        0, 18, 12, 12, 13, 1, 0, 19,
+        0, 20, 0, 21, 9, 9, 10, 1,
+        0, 22, 0, 23, 0, 24, 6, 6,
+        7, 1, 0, 25, 0, 26, 0, 2,
+        3, 3, 4, 1, 0, 0, 0, 0,
+        27, 0, 28, 3, 3, 4, 1, 0,
+        28, 3, 3, 4, 1, 0, 0, 0,
+        0, 29, 0, 30, 3, 3, 4, 1,
+        0, 30, 3, 3, 4, 1, 0, 0,
+        0, 0, 31, 0, 32, 3, 3, 4,
+        1, 0, 32, 3, 3, 4, 1, 0,
+        0, 0, 0, 33, 0, 34, 3, 3,
+        4, 1, 0, 34, 3, 3, 4, 1,
+        0, 0, 0, 0, 35, 0, 37, 36,
+        38, 39, 39, 40, 37, 36, 41, 41,
+        40, 36, 40, 36, 42, 42, 43, 37,
+        36, 44, 44, 43, 36, 43, 36, 45,
+        45, 46, 37, 36, 47, 47, 46, 36,
+        46, 36, 48, 48, 49, 37, 36, 50,
+        50, 49, 36, 49, 36, 51, 36, 36,
+        36, 37, 36, 52, 36, 53, 36, 54,
+        48, 48, 49, 37, 36, 55, 36, 56,
+        36, 57, 45, 45, 46, 37, 36, 58,
+        36, 59, 36, 60, 42, 42, 43, 37,
+        36, 61, 36, 62, 36, 38, 39, 39,
+        40, 37, 36, 36, 36, 36, 63, 36,
+        64, 39, 39, 40, 37, 36, 64, 39,
+        39, 40, 37, 36, 36, 36, 36, 65,
+        36, 66, 39, 39, 40, 37, 36, 66,
+        39, 39, 40, 37, 36, 36, 36, 36,
+        67, 36, 68, 39, 39, 40, 37, 36,
+        68, 39, 39, 40, 37, 36, 36, 36,
+        36, 69, 36, 70, 39, 39, 40, 37,
+        36, 70, 39, 39, 40, 37, 36, 36,
+        36, 36, 71, 36, 73, 72, 74, 75,
+        75, 76, 73, 72, 78, 78, 76, 77,
+        76, 77, 79, 79, 80, 73, 72, 81,
+        81, 80, 72, 80, 72, 82, 82, 83,
+        73, 72, 84, 84, 83, 72, 83, 72,
+        85, 85, 86, 73, 72, 87, 87, 86,
+        72, 86, 72, 88, 72, 72, 72, 73,
+        72, 89, 72, 90, 72, 91, 85, 85,
+        86, 73, 72, 92, 72, 93, 72, 94,
+        82, 82, 83, 73, 72, 95, 72, 96,
+        72, 97, 79, 79, 80, 73, 72, 98,
+        72, 99, 72, 74, 75, 75, 76, 73,
+        72, 72, 72, 72, 100, 72, 101, 75,
+        75, 76, 73, 72, 101, 75, 75, 76,
+        73, 72, 72, 72, 72, 102, 72, 103,
+        75, 75, 76, 73, 72, 103, 75, 75,
+        76, 73, 72, 72, 72, 72, 104, 72,
+        105, 75, 75, 76, 73, 72, 105, 75,
+        75, 76, 73, 72, 72, 72, 72, 106,
+        72, 107, 75, 75, 76, 73, 72, 109,
+        108, 110, 111, 111, 112, 109, 108, 113,
+        113, 112, 108, 112, 108, 114, 114, 115,
+        109, 108, 116, 116, 115, 108, 115, 108,
+        117, 117, 118, 109, 108, 119, 119, 118,
+        108, 118, 108, 120, 120, 121, 109, 108,
+        122, 122, 121, 108, 121, 108, 123, 108,
+        108, 108, 109, 108, 124, 108, 125, 108,
+        126, 120, 120, 121, 109, 108, 127, 108,
+        128, 108, 129, 117, 117, 118, 109, 108,
+        130, 108, 131, 108, 132, 114, 114, 115,
+        109, 108, 133, 108, 134, 108, 110, 111,
+        111, 112, 109, 108, 108, 108, 108, 135,
+        108, 136, 111, 111, 112, 109, 108, 136,
+        111, 111, 112, 109, 108, 108, 108, 108,
+        137, 108, 138, 111, 111, 112, 109, 108,
+        138, 111, 111, 112, 109, 108, 108, 108,
+        108, 139, 108, 140, 111, 111, 112, 109,
+        108, 140, 111, 111, 112, 109, 108, 108,
+        108, 108, 141, 108, 142, 111, 111, 112,
+        109, 108, 142, 111, 111, 112, 109, 108,
+        108, 108, 108, 143, 108, 107, 75, 75,
+        76, 73, 72, 72, 72, 72, 144, 72,
+        78, 78, 76, 1, 0, 146, 145, 148,
+        149, 150, 151, 152, 153, 76, 73, 147,
+        154, 155, 155, 144, 147, 156, 157, 147,
+        158, 159, 147, 161, 162, 163, 164, 4,
+        1, 160, 165, 160, 160, 35, 160, 166,
+        162, 167, 167, 4, 1, 160, 165, 160,
+        162, 167, 167, 4, 1, 160, 165, 160,
+        168, 160, 160, 160, 17, 169, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 168,
+        160, 170, 171, 172, 173, 4, 1, 160,
+        165, 160, 160, 33, 160, 174, 171, 175,
+        175, 4, 1, 160, 165, 160, 171, 175,
+        175, 4, 1, 160, 165, 160, 176, 160,
+        160, 160, 17, 177, 160, 1, 160, 165,
+        160, 160, 160, 160, 160, 176, 160, 178,
+        179, 180, 181, 4, 1, 160, 165, 160,
+        160, 31, 160, 182, 179, 183, 183, 4,
+        1, 160, 165, 160, 179, 183, 183, 4,
+        1, 160, 165, 160, 184, 160, 160, 160,
+        17, 185, 160, 1, 160, 165, 160, 160,
+        160, 160, 160, 184, 160, 186, 187, 188,
+        189, 4, 1, 160, 165, 160, 160, 29,
+        160, 190, 187, 191, 191, 4, 1, 160,
+        165, 160, 187, 191, 191, 4, 1, 160,
+        165, 160, 192, 160, 160, 160, 17, 193,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 192, 160, 194, 195, 196, 197, 4,
+        1, 160, 165, 160, 160, 27, 160, 198,
+        195, 199, 199, 4, 1, 160, 165, 160,
+        195, 199, 199, 4, 1, 160, 165, 160,
+        17, 200, 160, 1, 160, 165, 160, 201,
+        201, 160, 1, 160, 165, 160, 202, 160,
+        160, 203, 160, 165, 160, 165, 160, 204,
+        160, 205, 160, 202, 160, 160, 160, 160,
+        165, 160, 17, 160, 201, 201, 160, 1,
+        160, 165, 160, 201, 200, 160, 1, 160,
+        165, 160, 206, 26, 207, 208, 7, 1,
+        160, 165, 160, 26, 207, 208, 7, 1,
+        160, 165, 160, 207, 207, 7, 1, 160,
+        165, 160, 209, 23, 210, 211, 10, 1,
+        160, 165, 160, 23, 210, 211, 10, 1,
+        160, 165, 160, 210, 210, 10, 1, 160,
+        165, 160, 212, 20, 213, 214, 13, 1,
+        160, 165, 160, 20, 213, 214, 13, 1,
+        160, 165, 160, 213, 213, 13, 1, 160,
+        165, 160, 215, 17, 201, 216, 160, 1,
+        160, 165, 160, 17, 201, 216, 160, 1,
+        160, 165, 160, 194, 195, 199, 199, 4,
+        1, 160, 165, 160, 194, 195, 196, 199,
+        4, 1, 160, 165, 160, 160, 27, 160,
+        192, 160, 217, 160, 201, 201, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 192,
+        160, 192, 160, 160, 160, 201, 201, 160,
+        1, 160, 165, 160, 160, 160, 160, 160,
+        192, 160, 192, 160, 160, 160, 201, 193,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 192, 160, 186, 187, 191, 191, 4,
+        1, 160, 165, 160, 186, 187, 188, 191,
+        4, 1, 160, 165, 160, 160, 29, 160,
+        184, 160, 218, 160, 201, 201, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 184,
+        160, 184, 160, 160, 160, 201, 201, 160,
+        1, 160, 165, 160, 160, 160, 160, 160,
+        184, 160, 184, 160, 160, 160, 201, 185,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 184, 160, 178, 179, 183, 183, 4,
+        1, 160, 165, 160, 178, 179, 180, 183,
+        4, 1, 160, 165, 160, 160, 31, 160,
+        176, 160, 219, 160, 201, 201, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 176,
+        160, 176, 160, 160, 160, 201, 201, 160,
+        1, 160, 165, 160, 160, 160, 160, 160,
+        176, 160, 176, 160, 160, 160, 201, 177,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 176, 160, 170, 171, 175, 175, 4,
+        1, 160, 165, 160, 170, 171, 172, 175,
+        4, 1, 160, 165, 160, 160, 33, 160,
+        168, 160, 220, 160, 201, 201, 160, 1,
+        160, 165, 160, 160, 160, 160, 160, 168,
+        160, 168, 160, 160, 160, 201, 201, 160,
+        1, 160, 165, 160, 160, 160, 160, 160,
+        168, 160, 168, 160, 160, 160, 201, 169,
+        160, 1, 160, 165, 160, 160, 160, 160,
+        160, 168, 160, 161, 162, 167, 167, 4,
+        1, 160, 165, 160, 161, 162, 163, 167,
+        4, 1, 160, 165, 160, 160, 35, 160,
+        222, 223, 224, 225, 40, 37, 221, 226,
+        221, 221, 71, 221, 227, 223, 228, 225,
+        40, 37, 221, 226, 221, 223, 228, 225,
+        40, 37, 221, 226, 221, 229, 221, 221,
+        221, 53, 230, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 229, 221, 231, 232,
+        233, 234, 40, 37, 221, 226, 221, 221,
+        69, 221, 235, 232, 236, 236, 40, 37,
+        221, 226, 221, 232, 236, 236, 40, 37,
+        221, 226, 221, 237, 221, 221, 221, 53,
+        238, 221, 37, 221, 226, 221, 221, 221,
+        221, 221, 237, 221, 239, 240, 241, 242,
+        40, 37, 221, 226, 221, 221, 67, 221,
+        243, 240, 244, 244, 40, 37, 221, 226,
+        221, 240, 244, 244, 40, 37, 221, 226,
+        221, 245, 221, 221, 221, 53, 246, 221,
+        37, 221, 226, 221, 221, 221, 221, 221,
+        245, 221, 247, 248, 249, 250, 40, 37,
+        221, 226, 221, 221, 65, 221, 251, 248,
+        252, 252, 40, 37, 221, 226, 221, 248,
+        252, 252, 40, 37, 221, 226, 221, 253,
+        221, 221, 221, 53, 254, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 253, 221,
+        255, 256, 257, 258, 40, 37, 221, 226,
+        221, 221, 63, 221, 259, 256, 260, 260,
+        40, 37, 221, 226, 221, 256, 260, 260,
+        40, 37, 221, 226, 221, 53, 261, 221,
+        37, 221, 226, 221, 262, 262, 221, 37,
+        221, 226, 221, 263, 221, 221, 264, 221,
+        226, 221, 226, 221, 265, 221, 266, 221,
+        263, 221, 221, 221, 221, 226, 221, 53,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        262, 261, 221, 37, 221, 226, 221, 267,
+        62, 268, 269, 43, 37, 221, 226, 221,
+        62, 268, 269, 43, 37, 221, 226, 221,
+        268, 268, 43, 37, 221, 226, 221, 270,
+        59, 271, 272, 46, 37, 221, 226, 221,
+        59, 271, 272, 46, 37, 221, 226, 221,
+        271, 271, 46, 37, 221, 226, 221, 273,
+        56, 274, 275, 49, 37, 221, 226, 221,
+        56, 274, 275, 49, 37, 221, 226, 221,
+        274, 274, 49, 37, 221, 226, 221, 276,
+        53, 262, 277, 221, 37, 221, 226, 221,
+        53, 262, 277, 221, 37, 221, 226, 221,
+        255, 256, 260, 260, 40, 37, 221, 226,
+        221, 255, 256, 257, 260, 40, 37, 221,
+        226, 221, 221, 63, 221, 253, 221, 278,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 253, 221, 253, 221,
+        221, 221, 262, 262, 221, 37, 221, 226,
+        221, 221, 221, 221, 221, 253, 221, 253,
+        221, 221, 221, 262, 254, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 253, 221,
+        247, 248, 252, 252, 40, 37, 221, 226,
+        221, 247, 248, 249, 252, 40, 37, 221,
+        226, 221, 221, 65, 221, 245, 221, 279,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 245, 221, 245, 221,
+        221, 221, 262, 262, 221, 37, 221, 226,
+        221, 221, 221, 221, 221, 245, 221, 245,
+        221, 221, 221, 262, 246, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 245, 221,
+        239, 240, 244, 244, 40, 37, 221, 226,
+        221, 239, 240, 241, 244, 40, 37, 221,
+        226, 221, 221, 67, 221, 237, 221, 280,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 237, 221, 237, 221,
+        221, 221, 262, 262, 221, 37, 221, 226,
+        221, 221, 221, 221, 221, 237, 221, 237,
+        221, 221, 221, 262, 238, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 237, 221,
+        231, 232, 236, 236, 40, 37, 221, 226,
+        221, 231, 232, 233, 236, 40, 37, 221,
+        226, 221, 221, 69, 221, 229, 221, 281,
+        221, 262, 262, 221, 37, 221, 226, 221,
+        221, 221, 221, 221, 229, 221, 229, 221,
+        221, 221, 262, 262, 221, 37, 221, 226,
+        221, 221, 221, 221, 221, 229, 221, 229,
+        221, 221, 221, 262, 230, 221, 37, 221,
+        226, 221, 221, 221, 221, 221, 229, 221,
+        70, 39, 39, 40, 37, 221, 222, 223,
+        228, 225, 40, 37, 221, 226, 221, 283,
+        151, 284, 284, 76, 73, 282, 154, 282,
+        151, 284, 284, 76, 73, 282, 154, 282,
+        285, 282, 282, 282, 90, 286, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 285,
+        282, 287, 288, 289, 290, 76, 73, 282,
+        154, 282, 282, 106, 282, 291, 288, 292,
+        292, 76, 73, 282, 154, 282, 288, 292,
+        292, 76, 73, 282, 154, 282, 293, 282,
+        282, 282, 90, 294, 282, 73, 282, 154,
+        282, 282, 282, 282, 282, 293, 282, 295,
+        296, 297, 298, 76, 73, 282, 154, 282,
+        282, 104, 282, 299, 296, 300, 300, 76,
+        73, 282, 154, 282, 296, 300, 300, 76,
+        73, 282, 154, 282, 301, 282, 282, 282,
+        90, 302, 282, 73, 282, 154, 282, 282,
+        282, 282, 282, 301, 282, 303, 304, 305,
+        306, 76, 73, 282, 154, 282, 282, 102,
+        282, 307, 304, 308, 308, 76, 73, 282,
+        154, 282, 304, 308, 308, 76, 73, 282,
+        154, 282, 309, 282, 282, 282, 90, 310,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 309, 282, 311, 312, 313, 314, 76,
+        73, 282, 154, 282, 282, 100, 282, 315,
+        312, 316, 316, 76, 73, 282, 154, 282,
+        312, 316, 316, 76, 73, 282, 154, 282,
+        90, 317, 282, 73, 282, 154, 282, 318,
+        318, 282, 73, 282, 154, 282, 319, 282,
+        282, 320, 282, 154, 282, 154, 282, 321,
+        282, 322, 282, 319, 282, 282, 282, 282,
+        154, 282, 90, 282, 318, 318, 282, 73,
+        282, 154, 282, 318, 317, 282, 73, 282,
+        154, 282, 323, 99, 324, 325, 80, 73,
+        282, 154, 282, 99, 324, 325, 80, 73,
+        282, 154, 282, 324, 324, 80, 73, 282,
+        154, 282, 326, 96, 327, 328, 83, 73,
+        282, 154, 282, 96, 327, 328, 83, 73,
+        282, 154, 282, 327, 327, 83, 73, 282,
+        154, 282, 329, 93, 330, 331, 86, 73,
+        282, 154, 282, 93, 330, 331, 86, 73,
+        282, 154, 282, 330, 330, 86, 73, 282,
+        154, 282, 332, 90, 318, 333, 282, 73,
+        282, 154, 282, 90, 318, 333, 282, 73,
+        282, 154, 282, 311, 312, 316, 316, 76,
+        73, 282, 154, 282, 311, 312, 313, 316,
+        76, 73, 282, 154, 282, 282, 100, 282,
+        309, 282, 334, 282, 318, 318, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 309,
+        282, 309, 282, 282, 282, 318, 318, 282,
+        73, 282, 154, 282, 282, 282, 282, 282,
+        309, 282, 309, 282, 282, 282, 318, 310,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 309, 282, 303, 304, 308, 308, 76,
+        73, 282, 154, 282, 303, 304, 305, 308,
+        76, 73, 282, 154, 282, 282, 102, 282,
+        301, 282, 335, 282, 318, 318, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 301,
+        282, 301, 282, 282, 282, 318, 318, 282,
+        73, 282, 154, 282, 282, 282, 282, 282,
+        301, 282, 301, 282, 282, 282, 318, 302,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 301, 282, 295, 296, 300, 300, 76,
+        73, 282, 154, 282, 295, 296, 297, 300,
+        76, 73, 282, 154, 282, 282, 104, 282,
+        293, 282, 336, 282, 318, 318, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 293,
+        282, 293, 282, 282, 282, 318, 318, 282,
+        73, 282, 154, 282, 282, 282, 282, 282,
+        293, 282, 293, 282, 282, 282, 318, 294,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 293, 282, 287, 288, 292, 292, 76,
+        73, 282, 154, 282, 287, 288, 289, 292,
+        76, 73, 282, 154, 282, 282, 106, 282,
+        285, 282, 337, 282, 318, 318, 282, 73,
+        282, 154, 282, 282, 282, 282, 282, 285,
+        282, 285, 282, 282, 282, 318, 318, 282,
+        73, 282, 154, 282, 282, 282, 282, 282,
+        285, 282, 285, 282, 282, 282, 318, 286,
+        282, 73, 282, 154, 282, 282, 282, 282,
+        282, 285, 282, 107, 75, 75, 76, 73,
+        338, 338, 338, 338, 144, 338, 150, 151,
+        284, 284, 76, 73, 282, 154, 282, 107,
+        75, 75, 76, 73, 338, 340, 341, 342,
+        343, 112, 109, 339, 344, 339, 339, 143,
+        339, 345, 341, 343, 343, 112, 109, 339,
+        344, 339, 341, 343, 343, 112, 109, 339,
+        344, 339, 346, 339, 339, 339, 125, 347,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 346, 339, 348, 349, 350, 351, 112,
+        109, 339, 344, 339, 339, 141, 339, 352,
+        349, 353, 353, 112, 109, 339, 344, 339,
+        349, 353, 353, 112, 109, 339, 344, 339,
+        354, 339, 339, 339, 125, 355, 339, 109,
+        339, 344, 339, 339, 339, 339, 339, 354,
+        339, 356, 357, 358, 359, 112, 109, 339,
+        344, 339, 339, 139, 339, 360, 357, 361,
+        361, 112, 109, 339, 344, 339, 357, 361,
+        361, 112, 109, 339, 344, 339, 362, 339,
+        339, 339, 125, 363, 339, 109, 339, 344,
+        339, 339, 339, 339, 339, 362, 339, 364,
+        365, 366, 367, 112, 109, 339, 344, 339,
+        339, 137, 339, 368, 365, 369, 369, 112,
+        109, 339, 344, 339, 365, 369, 369, 112,
+        109, 339, 344, 339, 370, 339, 339, 339,
+        125, 371, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 370, 339, 372, 373, 374,
+        375, 112, 109, 339, 344, 339, 339, 135,
+        339, 376, 373, 377, 377, 112, 109, 339,
+        344, 339, 373, 377, 377, 112, 109, 339,
+        344, 339, 125, 378, 339, 109, 339, 344,
+        339, 379, 379, 339, 109, 339, 344, 339,
+        380, 339, 339, 381, 339, 344, 339, 344,
+        339, 382, 339, 383, 339, 380, 339, 339,
+        339, 339, 344, 339, 125, 339, 379, 379,
+        339, 109, 339, 344, 339, 379, 378, 339,
+        109, 339, 344, 339, 384, 134, 385, 386,
+        115, 109, 339, 344, 339, 134, 385, 386,
+        115, 109, 339, 344, 339, 385, 385, 115,
+        109, 339, 344, 339, 387, 131, 388, 389,
+        118, 109, 339, 344, 339, 131, 388, 389,
+        118, 109, 339, 344, 339, 388, 388, 118,
+        109, 339, 344, 339, 390, 128, 391, 392,
+        121, 109, 339, 344, 339, 128, 391, 392,
+        121, 109, 339, 344, 339, 391, 391, 121,
+        109, 339, 344, 339, 393, 125, 379, 394,
+        339, 109, 339, 344, 339, 125, 379, 394,
+        339, 109, 339, 344, 339, 372, 373, 377,
+        377, 112, 109, 339, 344, 339, 372, 373,
+        374, 377, 112, 109, 339, 344, 339, 339,
+        135, 339, 370, 339, 395, 339, 379, 379,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 370, 339, 370, 339, 339, 339, 379,
+        379, 339, 109, 339, 344, 339, 339, 339,
+        339, 339, 370, 339, 370, 339, 339, 339,
+        379, 371, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 370, 339, 364, 365, 369,
+        369, 112, 109, 339, 344, 339, 364, 365,
+        366, 369, 112, 109, 339, 344, 339, 339,
+        137, 339, 362, 339, 396, 339, 379, 379,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 362, 339, 362, 339, 339, 339, 379,
+        379, 339, 109, 339, 344, 339, 339, 339,
+        339, 339, 362, 339, 362, 339, 339, 339,
+        379, 363, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 362, 339, 356, 357, 361,
+        361, 112, 109, 339, 344, 339, 356, 357,
+        358, 361, 112, 109, 339, 344, 339, 339,
+        139, 339, 354, 339, 397, 339, 379, 379,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 354, 339, 354, 339, 339, 339, 379,
+        379, 339, 109, 339, 344, 339, 339, 339,
+        339, 339, 354, 339, 354, 339, 339, 339,
+        379, 355, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 354, 339, 348, 349, 353,
+        353, 112, 109, 339, 344, 339, 348, 349,
+        350, 353, 112, 109, 339, 344, 339, 339,
+        141, 339, 346, 339, 398, 339, 379, 379,
+        339, 109, 339, 344, 339, 339, 339, 339,
+        339, 346, 339, 346, 339, 339, 339, 379,
+        379, 339, 109, 339, 344, 339, 339, 339,
+        339, 339, 346, 339, 346, 339, 339, 339,
+        379, 347, 339, 109, 339, 344, 339, 339,
+        339, 339, 339, 346, 339, 340, 341, 343,
+        343, 112, 109, 339, 344, 339, 148, 149,
+        150, 151, 399, 284, 76, 73, 282, 154,
+        155, 155, 144, 282, 282, 148, 282, 161,
+        400, 163, 164, 4, 1, 160, 165, 160,
+        160, 35, 160, 168, 149, 150, 151, 401,
+        402, 76, 403, 160, 404, 160, 155, 144,
+        160, 160, 168, 160, 107, 405, 405, 76,
+        403, 160, 165, 160, 160, 144, 160, 406,
+        160, 160, 407, 160, 404, 160, 404, 160,
+        408, 160, 205, 160, 406, 160, 160, 160,
+        160, 404, 160, 168, 160, 220, 107, 405,
+        405, 76, 403, 160, 165, 160, 160, 160,
+        160, 160, 168, 160, 410, 409, 411, 411,
+        409, 146, 409, 412, 409, 411, 411, 409,
+        146, 409, 412, 409, 413, 409, 409, 414,
+        409, 412, 409, 412, 409, 415, 409, 416,
+        409, 413, 409, 409, 409, 409, 412, 409,
+        148, 338, 338, 338, 338, 338, 338, 338,
+        338, 338, 155, 338, 338, 338, 338, 148,
+        338, 0
 };
 
 static const short _indic_syllable_machine_trans_targs[] = {
-        166, 188, 2, 194, 3, 5, 197, 6,
-        8, 200, 9, 11, 203, 12, 14, 15,
-        187, 17, 18, 202, 20, 21, 199, 23,
-        24, 196, 205, 208, 212, 214, 218, 220,
-        224, 226, 230, 232, 166, 255, 37, 261,
-        38, 40, 264, 41, 43, 267, 44, 46,
-        270, 47, 49, 50, 254, 52, 53, 269,
-        55, 56, 266, 58, 59, 263, 272, 275,
-        279, 281, 285, 287, 291, 293, 297, 300,
-        166, 321, 72, 327, 166, 73, 75, 330,
-        76, 78, 333, 79, 81, 336, 82, 84,
-        85, 320, 87, 88, 335, 90, 91, 332,
-        93, 94, 329, 338, 341, 345, 347, 351,
-        353, 357, 359, 363, 166, 389, 106, 395,
-        107, 109, 398, 110, 112, 401, 113, 115,
-        404, 116, 118, 119, 388, 121, 122, 403,
-        124, 125, 400, 127, 128, 397, 406, 409,
-        413, 415, 419, 421, 425, 427, 431, 433,
-        366, 142, 444, 144, 447, 438, 145, 147,
-        450, 148, 150, 453, 151, 154, 155, 455,
-        157, 158, 452, 160, 161, 449, 163, 164,
-        446, 166, 458, 166, 167, 234, 301, 303,
-        365, 367, 323, 368, 434, 435, 340, 456,
-        463, 166, 168, 170, 34, 233, 190, 207,
-        169, 33, 171, 228, 172, 174, 32, 227,
-        173, 31, 175, 222, 176, 178, 30, 221,
-        177, 29, 179, 216, 180, 182, 28, 215,
-        181, 27, 183, 210, 184, 186, 26, 209,
-        185, 25, 193, 0, 189, 192, 191, 166,
-        1, 195, 4, 22, 198, 7, 19, 201,
-        10, 16, 204, 13, 206, 211, 213, 217,
-        219, 223, 225, 229, 231, 166, 235, 237,
-        69, 299, 257, 274, 236, 68, 238, 295,
-        239, 241, 67, 294, 240, 66, 242, 289,
-        243, 245, 65, 288, 244, 64, 246, 283,
-        247, 249, 63, 282, 248, 62, 250, 277,
-        251, 253, 61, 276, 252, 60, 260, 35,
-        256, 259, 258, 166, 36, 262, 39, 57,
-        265, 42, 54, 268, 45, 51, 271, 48,
-        273, 278, 280, 284, 286, 290, 292, 296,
-        298, 166, 302, 103, 304, 361, 305, 307,
-        102, 360, 306, 101, 308, 355, 309, 311,
-        100, 354, 310, 99, 312, 349, 313, 315,
-        98, 348, 314, 97, 316, 343, 317, 319,
-        96, 342, 318, 95, 326, 70, 322, 325,
-        324, 166, 71, 328, 74, 92, 331, 77,
-        89, 334, 80, 86, 337, 83, 339, 344,
-        346, 350, 352, 356, 358, 362, 364, 166,
-        166, 369, 371, 138, 137, 391, 408, 370,
-        372, 429, 373, 375, 136, 428, 374, 135,
-        376, 423, 377, 379, 134, 422, 378, 133,
-        380, 417, 381, 383, 132, 416, 382, 131,
-        384, 411, 385, 387, 130, 410, 386, 129,
-        394, 104, 390, 393, 392, 166, 105, 396,
-        108, 126, 399, 111, 123, 402, 114, 120,
-        405, 117, 407, 412, 414, 418, 420, 424,
-        426, 430, 432, 139, 436, 437, 443, 440,
-        140, 439, 442, 441, 141, 445, 143, 162,
-        448, 146, 159, 451, 149, 156, 454, 152,
-        153, 166, 457, 165, 460, 459, 462, 461,
-        166
+        138, 160, 166, 2, 167, 3, 5, 170,
+        6, 8, 173, 9, 11, 176, 12, 14,
+        15, 159, 17, 18, 175, 20, 21, 172,
+        23, 24, 169, 178, 182, 183, 187, 188,
+        192, 193, 197, 198, 138, 221, 227, 36,
+        228, 37, 39, 231, 40, 42, 234, 43,
+        45, 237, 46, 48, 49, 220, 51, 52,
+        236, 54, 55, 233, 57, 58, 230, 239,
+        243, 244, 248, 249, 253, 254, 258, 260,
+        138, 281, 287, 70, 288, 138, 71, 73,
+        291, 74, 76, 294, 77, 79, 297, 80,
+        82, 83, 280, 85, 86, 296, 88, 89,
+        293, 91, 92, 290, 299, 303, 304, 308,
+        309, 313, 314, 318, 138, 343, 349, 103,
+        350, 104, 106, 353, 107, 109, 356, 110,
+        112, 359, 113, 115, 116, 342, 118, 119,
+        358, 121, 122, 355, 124, 125, 352, 361,
+        365, 366, 370, 371, 375, 376, 380, 381,
+        320, 138, 394, 138, 139, 200, 261, 263,
+        319, 321, 283, 322, 382, 383, 392, 399,
+        138, 140, 142, 33, 199, 162, 141, 32,
+        143, 195, 144, 146, 31, 194, 145, 30,
+        147, 190, 148, 150, 29, 189, 149, 28,
+        151, 185, 152, 154, 27, 184, 153, 26,
+        155, 180, 156, 158, 25, 179, 157, 1,
+        165, 0, 161, 164, 163, 138, 168, 4,
+        22, 171, 7, 19, 174, 10, 16, 177,
+        13, 181, 186, 191, 196, 138, 201, 203,
+        67, 259, 223, 202, 66, 204, 256, 205,
+        207, 65, 255, 206, 64, 208, 251, 209,
+        211, 63, 250, 210, 62, 212, 246, 213,
+        215, 61, 245, 214, 60, 216, 241, 217,
+        219, 59, 240, 218, 35, 226, 34, 222,
+        225, 224, 138, 229, 38, 56, 232, 41,
+        53, 235, 44, 50, 238, 47, 242, 247,
+        252, 257, 138, 262, 100, 264, 316, 265,
+        267, 99, 315, 266, 98, 268, 311, 269,
+        271, 97, 310, 270, 96, 272, 306, 273,
+        275, 95, 305, 274, 94, 276, 301, 277,
+        279, 93, 300, 278, 69, 286, 68, 282,
+        285, 284, 138, 289, 72, 90, 292, 75,
+        87, 295, 78, 84, 298, 81, 302, 307,
+        312, 317, 138, 138, 323, 325, 134, 133,
+        345, 324, 326, 378, 327, 329, 132, 377,
+        328, 131, 330, 373, 331, 333, 130, 372,
+        332, 129, 334, 368, 335, 337, 128, 367,
+        336, 127, 338, 363, 339, 341, 126, 362,
+        340, 102, 348, 101, 344, 347, 346, 138,
+        351, 105, 123, 354, 108, 120, 357, 111,
+        117, 360, 114, 364, 369, 374, 379, 135,
+        384, 385, 391, 386, 388, 136, 387, 390,
+        389, 138, 393, 137, 396, 395, 398, 397,
+        138
 };
 
 static const char _indic_syllable_machine_trans_actions[] = {
-        1, 0, 0, 2, 0, 0, 2, 0,
-        0, 2, 0, 0, 2, 0, 0, 0,
-        2, 0, 0, 2, 0, 0, 2, 0,
-        0, 2, 2, 2, 2, 2, 2, 2,
-        2, 2, 2, 2, 3, 0, 0, 2,
-        0, 0, 2, 0, 0, 2, 0, 0,
-        2, 0, 0, 0, 2, 0, 0, 2,
-        0, 0, 2, 0, 0, 2, 2, 2,
-        2, 2, 2, 2, 2, 2, 2, 2,
-        4, 0, 0, 2, 5, 0, 0, 2,
+        1, 0, 2, 0, 2, 0, 0, 2,
         0, 0, 2, 0, 0, 2, 0, 0,
         0, 2, 0, 0, 2, 0, 0, 2,
-        0, 0, 2, 2, 6, 2, 6, 2,
-        6, 2, 6, 2, 7, 0, 0, 2,
-        0, 0, 2, 0, 0, 2, 0, 0,
-        2, 0, 0, 0, 2, 0, 0, 2,
-        0, 0, 2, 0, 0, 2, 2, 2,
+        0, 0, 2, 2, 2, 2, 2, 2,
+        2, 2, 2, 2, 3, 0, 2, 0,
+        2, 0, 0, 2, 0, 0, 2, 0,
+        0, 2, 0, 0, 0, 2, 0, 0,
+        2, 0, 0, 2, 0, 0, 2, 2,
         2, 2, 2, 2, 2, 2, 2, 2,
-        6, 0, 2, 0, 2, 0, 0, 0,
-        2, 0, 0, 2, 0, 0, 0, 2,
+        4, 0, 2, 0, 2, 5, 0, 0,
+        2, 0, 0, 2, 0, 0, 2, 0,
         0, 0, 2, 0, 0, 2, 0, 0,
-        2, 8, 0, 11, 2, 2, 6, 0,
-        12, 12, 0, 2, 6, 2, 6, 2,
-        0, 13, 2, 0, 0, 2, 0, 2,
-        2, 0, 2, 2, 2, 0, 0, 2,
-        2, 0, 2, 2, 2, 0, 0, 2,
-        2, 0, 2, 2, 2, 0, 0, 2,
-        2, 0, 2, 2, 2, 0, 0, 2,
-        2, 0, 2, 0, 0, 0, 0, 14,
-        0, 2, 0, 0, 2, 0, 0, 2,
-        0, 0, 2, 0, 2, 2, 2, 2,
-        2, 2, 2, 2, 2, 15, 2, 0,
-        0, 2, 0, 2, 2, 0, 2, 2,
-        2, 0, 0, 2, 2, 0, 2, 2,
-        2, 0, 0, 2, 2, 0, 2, 2,
-        2, 0, 0, 2, 2, 0, 2, 2,
-        2, 0, 0, 2, 2, 0, 2, 0,
-        0, 0, 0, 16, 0, 2, 0, 0,
+        2, 0, 0, 2, 6, 2, 6, 2,
+        6, 2, 6, 2, 7, 0, 2, 0,
         2, 0, 0, 2, 0, 0, 2, 0,
+        0, 2, 0, 0, 0, 2, 0, 0,
+        2, 0, 0, 2, 0, 0, 2, 2,
         2, 2, 2, 2, 2, 2, 2, 2,
-        2, 17, 6, 0, 6, 6, 6, 0,
-        0, 6, 6, 0, 6, 6, 6, 0,
-        0, 6, 6, 0, 6, 6, 6, 0,
-        0, 6, 6, 0, 6, 6, 6, 0,
-        0, 6, 6, 0, 6, 0, 0, 0,
-        0, 18, 0, 2, 0, 0, 2, 0,
-        0, 2, 0, 0, 2, 0, 2, 2,
-        2, 2, 2, 2, 2, 2, 2, 19,
-        20, 2, 0, 0, 0, 0, 2, 2,
+        6, 8, 0, 11, 2, 2, 6, 0,
+        12, 12, 0, 2, 6, 2, 2, 0,
+        13, 2, 0, 0, 2, 0, 2, 0,
         2, 2, 2, 0, 0, 2, 2, 0,
         2, 2, 2, 0, 0, 2, 2, 0,
         2, 2, 2, 0, 0, 2, 2, 0,
         2, 2, 2, 0, 0, 2, 2, 0,
-        2, 0, 0, 0, 0, 21, 0, 2,
-        0, 0, 2, 0, 0, 2, 0, 0,
-        2, 0, 2, 2, 2, 2, 2, 2,
-        2, 2, 2, 0, 0, 22, 2, 0,
-        0, 0, 0, 0, 0, 2, 0, 0,
+        2, 0, 0, 0, 0, 14, 2, 0,
+        0, 2, 0, 0, 2, 0, 0, 2,
+        0, 2, 2, 2, 2, 15, 2, 0,
+        0, 2, 0, 2, 0, 2, 2, 2,
+        0, 0, 2, 2, 0, 2, 2, 2,
+        0, 0, 2, 2, 0, 2, 2, 2,
+        0, 0, 2, 2, 0, 2, 2, 2,
+        0, 0, 2, 2, 0, 2, 0, 0,
+        0, 0, 16, 2, 0, 0, 2, 0,
+        0, 2, 0, 0, 2, 0, 2, 2,
+        2, 2, 17, 6, 0, 6, 2, 6,
+        0, 0, 6, 6, 0, 6, 2, 6,
+        0, 0, 6, 6, 0, 6, 2, 6,
+        0, 0, 6, 6, 0, 6, 2, 6,
+        0, 0, 6, 6, 0, 2, 0, 0,
+        0, 0, 18, 2, 0, 0, 2, 0,
+        0, 2, 0, 0, 2, 0, 2, 2,
+        2, 2, 19, 20, 2, 0, 0, 0,
+        0, 2, 2, 2, 2, 0, 0, 2,
+        2, 0, 2, 2, 2, 0, 0, 2,
+        2, 0, 2, 2, 2, 0, 0, 2,
+        2, 0, 2, 2, 2, 0, 0, 2,
+        2, 0, 2, 0, 0, 0, 0, 21,
         2, 0, 0, 2, 0, 0, 2, 0,
+        0, 2, 0, 2, 2, 2, 2, 0,
+        0, 22, 22, 0, 0, 0, 0, 0,
         0, 23, 2, 0, 0, 0, 0, 0,
         24
 };
@@ -937,15 +759,7 @@
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 9, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 9, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
@@ -998,15 +812,7 @@
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 10, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 10, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
@@ -1046,67 +852,59 @@
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 37, 37, 37, 37, 37,
+        1, 1, 37, 37, 37, 37, 37, 37,
         37, 37, 37, 37, 37, 37, 37, 37,
         37, 37, 37, 37, 37, 37, 37, 37,
         37, 37, 37, 37, 37, 37, 37, 37,
-        37, 37, 37, 37, 37, 37, 73, 73,
-        77, 77, 73, 73, 73, 73, 73, 73,
+        37, 37, 37, 37, 73, 73, 78, 78,
         73, 73, 73, 73, 73, 73, 73, 73,
         73, 73, 73, 73, 73, 73, 73, 73,
         73, 73, 73, 73, 73, 73, 73, 73,
-        109, 109, 109, 109, 109, 109, 109, 109,
+        73, 73, 73, 73, 73, 109, 109, 109,
         109, 109, 109, 109, 109, 109, 109, 109,
         109, 109, 109, 109, 109, 109, 109, 109,
         109, 109, 109, 109, 109, 109, 109, 109,
-        109, 109, 109, 73, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 1, 1, 1,
-        1, 1, 1, 1, 1, 170, 0, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 254, 254, 254,
-        254, 254, 254, 254, 254, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 322, 322, 322,
-        322, 322, 322, 322, 322, 384, 322, 384,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 385, 385, 385, 385, 385, 385,
-        385, 385, 322, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        186, 186, 186, 186, 186, 186, 186, 186,
-        474, 474, 474, 474, 474, 474, 474, 384
+        109, 109, 109, 109, 109, 109, 109, 73,
+        1, 146, 0, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 222, 222, 222,
+        222, 222, 222, 222, 222, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 283,
+        283, 283, 283, 283, 283, 283, 283, 339,
+        283, 339, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 340, 340,
+        340, 340, 340, 340, 340, 340, 283, 161,
+        161, 161, 161, 161, 161, 161, 161, 161,
+        410, 410, 410, 410, 410, 410, 410, 339
 };
 
-static const int indic_syllable_machine_start = 166;
-static const int indic_syllable_machine_first_final = 166;
+static const int indic_syllable_machine_start = 138;
+static const int indic_syllable_machine_first_final = 138;
 static const int indic_syllable_machine_error = -1;
 
-static const int indic_syllable_machine_en_main = 166;
+static const int indic_syllable_machine_en_main = 138;
 
 
 #line 36 "hb-ot-shape-complex-indic-machine.rl"
@@ -1118,10 +916,9 @@
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -1129,11 +926,11 @@
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 1137 "hb-ot-shape-complex-indic-machine.hh"
+#line 934 "hb-ot-shape-complex-indic-machine.hh"
         {
         cs = indic_syllable_machine_start;
         ts = 0;
@@ -1141,16 +938,15 @@
         act = 0;
         }
 
-#line 113 "hb-ot-shape-complex-indic-machine.rl"
+#line 112 "hb-ot-shape-complex-indic-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
 
-#line 1154 "hb-ot-shape-complex-indic-machine.hh"
+#line 950 "hb-ot-shape-complex-indic-machine.hh"
         {
         int _slen;
         int _trans;
@@ -1164,7 +960,7 @@
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 1168 "hb-ot-shape-complex-indic-machine.hh"
+#line 964 "hb-ot-shape-complex-indic-machine.hh"
         }
 
         _keys = _indic_syllable_machine_trans_keys + (cs<<1);
@@ -1287,7 +1083,7 @@
 #line 88 "hb-ot-shape-complex-indic-machine.rl"
         {act = 6;}
         break;
-#line 1291 "hb-ot-shape-complex-indic-machine.hh"
+#line 1087 "hb-ot-shape-complex-indic-machine.hh"
         }
 
 _again:
@@ -1296,7 +1092,7 @@
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 1300 "hb-ot-shape-complex-indic-machine.hh"
+#line 1096 "hb-ot-shape-complex-indic-machine.hh"
         }
 
         if ( ++p != pe )
@@ -1312,7 +1108,7 @@
 
         }
 
-#line 122 "hb-ot-shape-complex-indic-machine.rl"
+#line 120 "hb-ot-shape-complex-indic-machine.rl"
 
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,401 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-private.hh" /* XXX Remove */
-
-
-/* buffer var allocations */
-#define indic_category() complex_var_u8_0() /* indic_category_t */
-#define indic_position() complex_var_u8_1() /* indic_position_t */
-
-
-#define INDIC_TABLE_ELEMENT_TYPE uint16_t
-
-/* Cateories used in the OpenType spec:
- * https://docs.microsoft.com/en-us/typography/script-development/devanagari
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum indic_category_t {
-  OT_X = 0,
-  OT_C = 1,
-  OT_V = 2,
-  OT_N = 3,
-  OT_H = 4,
-  OT_ZWNJ = 5,
-  OT_ZWJ = 6,
-  OT_M = 7,
-  OT_SM = 8,
-  /* OT_VD = 9, UNUSED; we use OT_A instead. */
-  OT_A = 10,
-  OT_PLACEHOLDER = 11,
-  OT_DOTTEDCIRCLE = 12,
-  OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
-  OT_Coeng = 14, /* Khmer-style Virama. */
-  OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
-  OT_Ra = 16,
-  OT_CM = 17,  /* Consonant-Medial. */
-  OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
-  OT_CS = 19
-};
-
-#define MEDIAL_FLAGS (FLAG (OT_CM))
-
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants.  This is safe because Vowels
- * cannot happen in a consonant syllable.  The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
-#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
-
-
-/* Visual positions in a syllable from left to right. */
-enum indic_position_t {
-  POS_START = 0,
-
-  POS_RA_TO_BECOME_REPH = 1,
-  POS_PRE_M = 2,
-  POS_PRE_C = 3,
-
-  POS_BASE_C = 4,
-  POS_AFTER_MAIN = 5,
-
-  POS_ABOVE_C = 6,
-
-  POS_BEFORE_SUB = 7,
-  POS_BELOW_C = 8,
-  POS_AFTER_SUB = 9,
-
-  POS_BEFORE_POST = 10,
-  POS_POST_C = 11,
-  POS_AFTER_POST = 12,
-
-  POS_FINAL_C = 13,
-  POS_SMVD = 14,
-
-  POS_END = 15
-};
-
-/* Categories used in IndicSyllabicCategory.txt from UCD. */
-enum indic_syllabic_category_t {
-  INDIC_SYLLABIC_CATEGORY_OTHER                         = OT_X,
-
-  INDIC_SYLLABIC_CATEGORY_AVAGRAHA                      = OT_Symbol,
-  INDIC_SYLLABIC_CATEGORY_BINDU                         = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER         = OT_PLACEHOLDER, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK             = OT_A,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT                     = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD                = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL               = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER         = OT_C,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER              = OT_M, /* U+17CD only. */
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL              = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER         = OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA     = OT_Repha,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED            = OT_X, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED           = OT_CM,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA    = OT_N,
-  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER        = OT_CS,
-  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK               = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
-  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER             = OT_Coeng,
-  INDIC_SYLLABIC_CATEGORY_JOINER                        = OT_ZWJ,
-  INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER              = OT_X,
-  INDIC_SYLLABIC_CATEGORY_NON_JOINER                    = OT_ZWNJ,
-  INDIC_SYLLABIC_CATEGORY_NUKTA                         = OT_N,
-  INDIC_SYLLABIC_CATEGORY_NUMBER                        = OT_PLACEHOLDER,
-  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER                 = OT_PLACEHOLDER, /* Don't care. */
-  INDIC_SYLLABIC_CATEGORY_PURE_KILLER                   = OT_M, /* Is like a vowel matra. */
-  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER              = OT_RS,
-  INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER             = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_TONE_LETTER                   = OT_X,
-  INDIC_SYLLABIC_CATEGORY_TONE_MARK                     = OT_N,
-  INDIC_SYLLABIC_CATEGORY_VIRAMA                        = OT_H,
-  INDIC_SYLLABIC_CATEGORY_VISARGA                       = OT_SM,
-  INDIC_SYLLABIC_CATEGORY_VOWEL                         = OT_V,
-  INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT               = OT_M,
-  INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT             = OT_V
-};
-
-/* Categories used in IndicSMatraCategory.txt from UCD */
-enum indic_matra_category_t {
-  INDIC_MATRA_CATEGORY_NOT_APPLICABLE                   = POS_END,
-
-  INDIC_MATRA_CATEGORY_LEFT                             = POS_PRE_C,
-  INDIC_MATRA_CATEGORY_TOP                              = POS_ABOVE_C,
-  INDIC_MATRA_CATEGORY_BOTTOM                           = POS_BELOW_C,
-  INDIC_MATRA_CATEGORY_RIGHT                            = POS_POST_C,
-
-  /* These should resolve to the position of the last part of the split sequence. */
-  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT                 = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                   = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                   = INDIC_MATRA_CATEGORY_BOTTOM,
-  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT         = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT                     = INDIC_MATRA_CATEGORY_TOP,
-  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT           = INDIC_MATRA_CATEGORY_RIGHT,
-  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT                    = INDIC_MATRA_CATEGORY_RIGHT,
-
-  INDIC_MATRA_CATEGORY_OVERSTRUCK                       = POS_AFTER_MAIN,
-  INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT                = POS_PRE_M
-};
-
-#define INDIC_COMBINE_CATEGORIES(S,M) \
-  ( \
-    ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
-    ( S | \
-     ( \
-      ( \
-       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
-       S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
-       S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
-       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
-       S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
-       S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
-       false \
-       ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
-      ) << 8 \
-     ) \
-    ) \
-   )
-
-HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
-hb_indic_get_categories (hb_codepoint_t u);
-
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
-  /* If it ligated, all bets are off. */
-  if (_hb_glyph_info_ligated (&info)) return false;
-  return !!(FLAG_UNSAFE (info.indic_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, CONSONANT_FLAGS);
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, FLAG (OT_H));
-}
-
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
-
-
-#define MATRA_POS_LEFT(u)       POS_PRE_M
-#define MATRA_POS_RIGHT(u)      ( \
-                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                  IS_BENG(u) ? POS_AFTER_POST : \
-                                  IS_GURU(u) ? POS_AFTER_POST : \
-                                  IS_GUJR(u) ? POS_AFTER_POST : \
-                                  IS_ORYA(u) ? POS_AFTER_POST : \
-                                  IS_TAML(u) ? POS_AFTER_POST : \
-                                  IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
-                                  IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
-                                  IS_MLYM(u) ? POS_AFTER_POST : \
-                                  IS_SINH(u) ? POS_AFTER_SUB  : \
-                                  /*default*/  POS_AFTER_SUB    \
-                                )
-#define MATRA_POS_TOP(u)        ( /* BENG and MLYM don't have top matras. */ \
-                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                  IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
-                                  IS_GUJR(u) ? POS_AFTER_SUB  : \
-                                  IS_ORYA(u) ? POS_AFTER_MAIN : \
-                                  IS_TAML(u) ? POS_AFTER_SUB  : \
-                                  IS_TELU(u) ? POS_BEFORE_SUB : \
-                                  IS_KNDA(u) ? POS_BEFORE_SUB : \
-                                  IS_SINH(u) ? POS_AFTER_SUB  : \
-                                  /*default*/  POS_AFTER_SUB    \
-                                )
-#define MATRA_POS_BOTTOM(u)     ( \
-                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
-                                  IS_BENG(u) ? POS_AFTER_SUB  : \
-                                  IS_GURU(u) ? POS_AFTER_POST : \
-                                  IS_GUJR(u) ? POS_AFTER_POST : \
-                                  IS_ORYA(u) ? POS_AFTER_SUB  : \
-                                  IS_TAML(u) ? POS_AFTER_POST : \
-                                  IS_TELU(u) ? POS_BEFORE_SUB : \
-                                  IS_KNDA(u) ? POS_BEFORE_SUB : \
-                                  IS_MLYM(u) ? POS_AFTER_POST : \
-                                  IS_SINH(u) ? POS_AFTER_SUB  : \
-                                  /*default*/  POS_AFTER_SUB    \
-                                )
-
-static inline indic_position_t
-matra_position_indic (hb_codepoint_t u, indic_position_t side)
-{
-  switch ((int) side)
-  {
-    case POS_PRE_C:     return MATRA_POS_LEFT (u);
-    case POS_POST_C:    return MATRA_POS_RIGHT (u);
-    case POS_ABOVE_C:   return MATRA_POS_TOP (u);
-    case POS_BELOW_C:   return MATRA_POS_BOTTOM (u);
-  };
-  return side;
-}
-
-/* XXX
- * This is a hack for now.  We should move this data into the main Indic table.
- * Or completely remove it and just check in the tables.
- */
-static const hb_codepoint_t ra_chars[] = {
-  0x0930u, /* Devanagari */
-  0x09B0u, /* Bengali */
-  0x09F0u, /* Bengali */
-  0x0A30u, /* Gurmukhi */       /* No Reph */
-  0x0AB0u, /* Gujarati */
-  0x0B30u, /* Oriya */
-  0x0BB0u, /* Tamil */          /* No Reph */
-  0x0C30u, /* Telugu */         /* Reph formed only with ZWJ */
-  0x0CB0u, /* Kannada */
-  0x0D30u, /* Malayalam */      /* No Reph, Logical Repha */
-
-  0x0DBBu, /* Sinhala */                /* Reph formed only with ZWJ */
-};
-
-static inline bool
-is_ra (hb_codepoint_t u)
-{
-  for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
-    if (u == ra_chars[i])
-      return true;
-  return false;
-}
-
-static inline void
-set_indic_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
-  indic_position_t pos = (indic_position_t) (type >> 8);
-
-
-  /*
-   * Re-assign category
-   */
-
-  /* The following act more like the Bindus. */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
-    cat = OT_SM;
-  /* The following act like consonants. */
-  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
-                                      0x1CF5u, 0x1CF6u)))
-    cat = OT_C;
-  /* TODO: The following should only be allowed after a Visarga.
-   * For now, just treat them like regular tone marks. */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
-    cat = OT_A;
-  /* TODO: The following should only be allowed after some of
-   * the nasalization marks, maybe only for U+1CE9..U+1CF1.
-   * For now, just treat them like tone marks. */
-  else if (unlikely (u == 0x1CEDu))
-    cat = OT_A;
-  /* The following take marks in standalone clusters, similar to Avagraha. */
-  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
-                                      0x1CE9u, 0x1CECu,
-                                      0x1CEEu, 0x1CF1u)))
-  {
-    cat = OT_Symbol;
-    static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
-  }
-  else if (unlikely (u == 0x0A51u))
-  {
-    /* https://github.com/harfbuzz/harfbuzz/issues/524 */
-    cat = OT_M;
-    pos = POS_BELOW_C;
-  }
-
-  /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
-   * so the Indic shaper needs to know their categories. */
-  else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
-  else if (unlikely (u == 0x1133cu)) cat = OT_N;
-
-  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
-
-  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
-  else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
-                                    cat = OT_PLACEHOLDER;
-  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
-  /*
-   * Re-assign position.
-   */
-
-  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
-  {
-    pos = POS_BASE_C;
-    if (is_ra (u))
-      cat = OT_Ra;
-  }
-  else if (cat == OT_M)
-  {
-    pos = matra_position_indic (u, pos);
-  }
-  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
-  {
-    pos = POS_SMVD;
-  }
-
-  if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
-
-
-
-  info.indic_category() = cat;
-  info.indic_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-table.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic-table.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -14,8 +14,10 @@
  * # Date: 2017-10-16, 24:39:00 GMT [KW]
  */
 
-#include "hb-ot-shape-complex-indic-private.hh"
+#include "hb-ot-shape-complex-indic.hh"
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 
 #define ISC_A   INDIC_SYLLABIC_CATEGORY_AVAGRAHA                /*  16 chars; Avagraha */
 #define ISC_Bi  INDIC_SYLLABIC_CATEGORY_BINDU                   /*  83 chars; Bindu */
@@ -69,6 +71,7 @@
 #define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT     /*   4 chars; Top_And_Left_And_Right */
 #define IMC_TR  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT              /*  13 chars; Top_And_Right */
 #define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT          /*  19 chars; Visual_Order_Left */
+#pragma GCC diagnostic pop
 
 #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,8 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-indic-private.hh"
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-shape-complex-indic.hh"
+#include "hb-ot-shape-complex-vowel-constraints.hh"
+#include "hb-ot-layout.hh"
 
 
 /*
@@ -95,42 +96,41 @@
  * Indic shaper.
  */
 
-struct feature_list_t {
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
+static const hb_ot_map_feature_t
 indic_features[] =
 {
   /*
    * Basic features.
    * These features are applied in order, one at a time, after initial_reordering.
    */
-  {HB_TAG('n','u','k','t'), F_GLOBAL},
-  {HB_TAG('a','k','h','n'), F_GLOBAL},
-  {HB_TAG('r','p','h','f'), F_NONE},
-  {HB_TAG('r','k','r','f'), F_GLOBAL},
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('h','a','l','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('v','a','t','u'), F_GLOBAL},
-  {HB_TAG('c','j','c','t'), F_GLOBAL},
+  {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('r','p','h','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','r','e','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('h','a','l','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','f'),        F_MANUAL_JOINERS},
+  {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
+   * These features are applied all at once, after final_reordering
+   * but before clearing syllables.
    * Default Bengali font in Windows for example has intermixed
    * lookups for init,pres,abvs,blws features.
    */
-  {HB_TAG('i','n','i','t'), F_NONE},
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  {HB_TAG('h','a','l','n'), F_GLOBAL},
-  /* Positioning features, though we don't care about the types. */
+  {HB_TAG('i','n','i','t'),        F_MANUAL_JOINERS},
+  {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   {HB_TAG('d','i','s','t'), F_GLOBAL},
   {HB_TAG('a','b','v','m'), F_GLOBAL},
   {HB_TAG('b','l','w','m'), F_GLOBAL},
@@ -158,12 +158,13 @@
   _BLWS,
   _PSTS,
   _HALN,
+
   _DIST,
   _ABVM,
   _BLWM,
 
   INDIC_NUM_FEATURES,
-  INDIC_BASIC_FEATURES = INIT /* Don't forget to update this! */
+  INDIC_BASIC_FEATURES = INIT, /* Don't forget to update this! */
 };
 
 static void
@@ -191,25 +192,27 @@
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
   /* The Indic specs do not require ccmp, but we apply it here since if
    * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
 
 
   unsigned int i = 0;
   map->add_gsub_pause (initial_reordering);
+
   for (; i < INDIC_BASIC_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
+    map->add_feature (indic_features[i]);
     map->add_gsub_pause (nullptr);
   }
+
   map->add_gsub_pause (final_reordering);
-  for (; i < INDIC_NUM_FEATURES; i++) {
-    map->add_feature (indic_features[i].tag, 1, indic_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-  }
 
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','l','i','g'));
+  for (; i < INDIC_NUM_FEATURES; i++)
+    map->add_feature (indic_features[i]);
+
+  map->enable_feature (HB_TAG('c','a','l','t'));
+  map->enable_feature (HB_TAG('c','l','i','g'));
 
   map->add_gsub_pause (clear_syllables);
 }
@@ -217,13 +220,13 @@
 static void
 override_features_indic (hb_ot_shape_planner_t *plan)
 {
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
 struct would_substitute_feature_t
 {
-  inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+  void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
   {
     zero_context = zero_context_;
     map->get_stage_lookups (0/*GSUB*/,
@@ -231,9 +234,9 @@
                             &lookups, &count);
   }
 
-  inline bool would_substitute (const hb_codepoint_t *glyphs,
-                                unsigned int          glyphs_count,
-                                hb_face_t            *face) const
+  bool would_substitute (const hb_codepoint_t *glyphs,
+                         unsigned int          glyphs_count,
+                         hb_face_t            *face) const
   {
     for (unsigned int i = 0; i < count; i++)
       if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
@@ -249,12 +252,10 @@
 
 struct indic_shape_plan_t
 {
-  ASSERT_POD ();
-
-  inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
+  bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
   {
-    hb_codepoint_t glyph = virama_glyph;
-    if (unlikely (virama_glyph == (hb_codepoint_t) -1))
+    hb_codepoint_t glyph = virama_glyph.get_relaxed ();
+    if (unlikely (glyph == (hb_codepoint_t) -1))
     {
       if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
         glyph = 0;
@@ -262,8 +263,8 @@
        * Maybe one day... */
 
       /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
-       * during shape planning...  Instead, overwrite it here.  It's safe.  Don't worry! */
-      virama_glyph = glyph;
+       * during shape planning...  Instead, overwrite it here. */
+      virama_glyph.set_relaxed ((int) glyph);
     }
 
     *pglyph = glyph;
@@ -273,7 +274,8 @@
   const indic_config_t *config;
 
   bool is_old_spec;
-  mutable hb_codepoint_t virama_glyph;
+  bool uniscribe_bug_compatible;
+  mutable hb_atomic_int_t virama_glyph;
 
   would_substitute_feature_t rphf;
   would_substitute_feature_t pref;
@@ -298,7 +300,8 @@
     }
 
   indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
-  indic_plan->virama_glyph = (hb_codepoint_t) -1;
+  indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
+  indic_plan->virama_glyph.set_relaxed (-1);
 
   /* Use zero-context would_substitute() matching for new-spec of the main
    * Indic scripts, and scripts with one spec only, but not for old-specs.
@@ -419,7 +422,7 @@
     return;
 
   hb_codepoint_t virama;
-  if (indic_plan->get_virama_glyph (font, &virama))
+  if (indic_plan->load_virama_glyph (font, &virama))
   {
     hb_face_t *face = font->face;
     unsigned int count = buffer->len;
@@ -667,10 +670,10 @@
    * last consonant.
    *
    * Reports suggest that in some scripts Uniscribe does this only if there
-   * is *not* a Halant after last consonant already (eg. Kannada), while it
-   * does it unconditionally in other scripts (eg. Malayalam, Bengali).  We
-   * don't currently know about other scripts, so we whitelist Malayalam and
-   * Bengali for now.
+   * is *not* a Halant after last consonant already.  We know that is the
+   * case for Kannada, while it reorders unconditionally in other scripts,
+   * eg. Malayalam, Bengali, and Devanagari.  We don't currently know about
+   * other scripts, so we blacklist Kannada.
    *
    * Kannada test case:
    * U+0C9A,U+0CCD,U+0C9A,U+0CCD
@@ -681,15 +684,19 @@
    * U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
    * With lohit-ttf-20121122/Lohit-Malayalam.ttf
    *
-   * Bengali test case
+   * Bengali test case:
    * U+0998,U+09CD,U+09AF,U+09CD
    * With Windows XP vrinda.ttf
    * https://github.com/harfbuzz/harfbuzz/issues/1073
+   *
+   * Devanagari test case:
+   * U+091F,U+094D,U+0930,U+094D
+   * With chandas.ttf
+   * https://github.com/harfbuzz/harfbuzz/issues/1071
    */
   if (indic_plan->is_old_spec)
   {
-    bool disallow_double_halants = buffer->props.script != HB_SCRIPT_MALAYALAM &&
-                                   buffer->props.script != HB_SCRIPT_BENGALI;
+    bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
     for (unsigned int i = base + 1; i < end; i++)
       if (info[i].indic_category() == OT_H)
       {
@@ -713,7 +720,7 @@
     indic_position_t last_pos = POS_START;
     for (unsigned int i = start; i < end; i++)
     {
-      if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_H))))
+      if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | FLAG (OT_H))))
       {
         info[i].indic_position() = last_pos;
         if (unlikely (info[i].indic_category() == OT_H &&
@@ -779,8 +786,10 @@
      *
      * We could use buffer->sort() for this, if there was no special
      * reordering of pre-base stuff happening later...
+     * We don't want to merge_clusters all of that, which buffer->sort()
+     * would.
      */
-    if (indic_plan->is_old_spec || end - base > 127)
+    if (indic_plan->is_old_spec || end - start > 127)
       buffer->merge_clusters (base, end);
     else
     {
@@ -909,10 +918,12 @@
                                        hb_buffer_t *buffer,
                                        unsigned int start, unsigned int end)
 {
+  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+
   /* We treat placeholder/dotted-circle as if they are consonants, so we
    * should just chain.  Only if not in compatibility mode that is... */
 
-  if (hb_options ().uniscribe_bug_compatible)
+  if (indic_plan->uniscribe_bug_compatible)
   {
     /* For dotted-circle, this is what Uniscribe does:
      * If dotted-circle is the last glyph, it just does nothing.
@@ -954,7 +965,8 @@
                        hb_font_t *font,
                        hb_buffer_t *buffer)
 {
-  /* Note: This loop is extra overhead, but should not be measurable. */
+  /* Note: This loop is extra overhead, but should not be measurable.
+   * TODO Use a buffer scratch flag to remove the loop. */
   bool has_broken_syllables = false;
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
@@ -1006,7 +1018,6 @@
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
@@ -1036,9 +1047,11 @@
    * phase, and that might have messed up our properties.  Recover
    * from a particular case of that where we're fairly sure that a
    * class of OT_H is desired but has been lost. */
-  if (indic_plan->virama_glyph)
+  /* We don't call load_virama_glyph(), since we know it's already
+   * loaded. */
+  hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
+  if (virama_glyph)
   {
-    unsigned int virama_glyph = indic_plan->virama_glyph;
     for (unsigned int i = start; i < end; i++)
       if (info[i].codepoint == virama_glyph &&
           _hb_glyph_info_ligated (&info[i]) &&
@@ -1127,6 +1140,24 @@
    *     defined as “after last standalone halant glyph, after initial matra
    *     position and before the main consonant”. If ZWJ or ZWNJ follow this
    *     halant, position is moved after it.
+   *
+   * IMPLEMENTATION NOTES:
+   *
+   * It looks like the last sentence is wrong.  Testing, with Windows 7 Uniscribe
+   * and Devanagari shows that the behavior is best described as:
+   *
+   * "If ZWJ follows this halant, matra is NOT repositioned after this halant.
+   *  If ZWNJ follows this halant, position is moved after it."
+   *
+   * Test case, with Adobe Devanagari or Nirmala UI:
+   *
+   *   U+091F,U+094D,U+200C,U+092F,U+093F
+   *   (Matra moves to the middle, after ZWNJ.)
+   *
+   *   U+091F,U+094D,U+200D,U+092F,U+093F
+   *   (Matra does NOT move, stays to the left.)
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1070
    */
 
   if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
@@ -1140,6 +1171,7 @@
      */
     if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
     {
+    search:
       while (new_pos > start &&
              !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H)))))
         new_pos--;
@@ -1150,9 +1182,27 @@
       if (is_halant (info[new_pos]) &&
           info[new_pos].indic_position() != POS_PRE_M)
       {
+#if 0 // See comment above
         /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
         if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
           new_pos++;
+#endif
+        if (new_pos + 1 < end)
+        {
+          /* -> If ZWJ follows this halant, matra is NOT repositioned after this halant. */
+          if (info[new_pos + 1].indic_category() == OT_ZWJ)
+          {
+            /* Keep searching. */
+            if (new_pos > start)
+            {
+              new_pos--;
+              goto search;
+            }
+          }
+          /* -> If ZWNJ follows this halant, position is moved after it. */
+          if (info[new_pos + 1].indic_category() == OT_ZWNJ)
+            new_pos++;
+        }
       }
       else
         new_pos = start; /* No move. */
@@ -1313,7 +1363,7 @@
        * Uniscribe doesn't do this.
        * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
        */
-      if (!hb_options ().uniscribe_bug_compatible &&
+      if (!indic_plan->uniscribe_bug_compatible &&
           unlikely (is_halant (info[new_reph_pos]))) {
         for (unsigned int i = base + 1; i < new_reph_pos; i++)
           if (info[i].indic_category() == OT_M) {
@@ -1419,7 +1469,7 @@
   /*
    * Finish off the clusters and go home!
    */
-  if (hb_options ().uniscribe_bug_compatible)
+  if (indic_plan->uniscribe_bug_compatible)
   {
     switch ((hb_tag_t) plan->props.script)
     {
@@ -1467,6 +1517,14 @@
 }
 
 
+static void
+preprocess_text_indic (const hb_ot_shape_plan_t *plan,
+                       hb_buffer_t              *buffer,
+                       hb_font_t                *font)
+{
+  _hb_preprocess_text_vowel_constraints (plan, buffer, font);
+}
+
 static bool
 decompose_indic (const hb_ot_shape_normalize_context_t *c,
                  hb_codepoint_t  ab,
@@ -1566,13 +1624,13 @@
   override_features_indic,
   data_create_indic,
   data_destroy_indic,
-  nullptr, /* preprocess_text */
+  preprocess_text_indic,
   nullptr, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   decompose_indic,
   compose_indic,
   setup_masks_indic,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-indic.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,399 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_INDIC_HH
+#define HB_OT_SHAPE_COMPLEX_INDIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+
+/* buffer var allocations */
+#define indic_category() complex_var_u8_0() /* indic_category_t */
+#define indic_position() complex_var_u8_1() /* indic_position_t */
+
+
+#define INDIC_TABLE_ELEMENT_TYPE uint16_t
+
+/* Cateories used in the OpenType spec:
+ * https://docs.microsoft.com/en-us/typography/script-development/devanagari
+ */
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum indic_category_t {
+  OT_X = 0,
+  OT_C = 1,
+  OT_V = 2,
+  OT_N = 3,
+  OT_H = 4,
+  OT_ZWNJ = 5,
+  OT_ZWJ = 6,
+  OT_M = 7,
+  OT_SM = 8,
+  /* OT_VD = 9, UNUSED; we use OT_A instead. */
+  OT_A = 10,
+  OT_PLACEHOLDER = 11,
+  OT_DOTTEDCIRCLE = 12,
+  OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
+  OT_Coeng = 14, /* Khmer-style Virama. */
+  OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
+  OT_Ra = 16,
+  OT_CM = 17,  /* Consonant-Medial; Unused by Indic shaper. */
+  OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
+  OT_CS = 19
+};
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants.  This is safe because Vowels
+ * cannot happen in a consonant syllable.  The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right! */
+#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
+#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
+
+
+/* Visual positions in a syllable from left to right. */
+enum indic_position_t {
+  POS_START = 0,
+
+  POS_RA_TO_BECOME_REPH = 1,
+  POS_PRE_M = 2,
+  POS_PRE_C = 3,
+
+  POS_BASE_C = 4,
+  POS_AFTER_MAIN = 5,
+
+  POS_ABOVE_C = 6,
+
+  POS_BEFORE_SUB = 7,
+  POS_BELOW_C = 8,
+  POS_AFTER_SUB = 9,
+
+  POS_BEFORE_POST = 10,
+  POS_POST_C = 11,
+  POS_AFTER_POST = 12,
+
+  POS_FINAL_C = 13,
+  POS_SMVD = 14,
+
+  POS_END = 15
+};
+
+/* Categories used in IndicSyllabicCategory.txt from UCD. */
+enum indic_syllabic_category_t {
+  INDIC_SYLLABIC_CATEGORY_OTHER                         = OT_X,
+
+  INDIC_SYLLABIC_CATEGORY_AVAGRAHA                      = OT_Symbol,
+  INDIC_SYLLABIC_CATEGORY_BINDU                         = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER         = OT_PLACEHOLDER, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK             = OT_A,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT                     = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD                = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL               = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER         = OT_C,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER              = OT_M, /* U+17CD only. */
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL              = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER         = OT_PLACEHOLDER,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA     = OT_Repha,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED            = OT_X, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED           = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA    = OT_CM,
+  INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER        = OT_CS,
+  INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK               = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
+  INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER             = OT_Coeng,
+  INDIC_SYLLABIC_CATEGORY_JOINER                        = OT_ZWJ,
+  INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER              = OT_X,
+  INDIC_SYLLABIC_CATEGORY_NON_JOINER                    = OT_ZWNJ,
+  INDIC_SYLLABIC_CATEGORY_NUKTA                         = OT_N,
+  INDIC_SYLLABIC_CATEGORY_NUMBER                        = OT_PLACEHOLDER,
+  INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER                 = OT_PLACEHOLDER, /* Don't care. */
+  INDIC_SYLLABIC_CATEGORY_PURE_KILLER                   = OT_M, /* Is like a vowel matra. */
+  INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER              = OT_RS,
+  INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER             = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_TONE_LETTER                   = OT_X,
+  INDIC_SYLLABIC_CATEGORY_TONE_MARK                     = OT_N,
+  INDIC_SYLLABIC_CATEGORY_VIRAMA                        = OT_H,
+  INDIC_SYLLABIC_CATEGORY_VISARGA                       = OT_SM,
+  INDIC_SYLLABIC_CATEGORY_VOWEL                         = OT_V,
+  INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT               = OT_M,
+  INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT             = OT_V
+};
+
+/* Categories used in IndicSMatraCategory.txt from UCD */
+enum indic_matra_category_t {
+  INDIC_MATRA_CATEGORY_NOT_APPLICABLE                   = POS_END,
+
+  INDIC_MATRA_CATEGORY_LEFT                             = POS_PRE_C,
+  INDIC_MATRA_CATEGORY_TOP                              = POS_ABOVE_C,
+  INDIC_MATRA_CATEGORY_BOTTOM                           = POS_BELOW_C,
+  INDIC_MATRA_CATEGORY_RIGHT                            = POS_POST_C,
+
+  /* These should resolve to the position of the last part of the split sequence. */
+  INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT                 = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT                   = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM                   = INDIC_MATRA_CATEGORY_BOTTOM,
+  INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT         = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_LEFT                     = INDIC_MATRA_CATEGORY_TOP,
+  INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT           = INDIC_MATRA_CATEGORY_RIGHT,
+  INDIC_MATRA_CATEGORY_TOP_AND_RIGHT                    = INDIC_MATRA_CATEGORY_RIGHT,
+
+  INDIC_MATRA_CATEGORY_OVERSTRUCK                       = POS_AFTER_MAIN,
+  INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT                = POS_PRE_M
+};
+
+#define INDIC_COMBINE_CATEGORIES(S,M) \
+  ( \
+    ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \
+    ( S | \
+     ( \
+      ( \
+       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
+       S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
+       S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
+       S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
+       S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
+       S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
+       false \
+       ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
+      ) << 8 \
+     ) \
+    ) \
+   )
+
+HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE
+hb_indic_get_categories (hb_codepoint_t u);
+
+
+static inline bool
+is_one_of (const hb_glyph_info_t &info, unsigned int flags)
+{
+  /* If it ligated, all bets are off. */
+  if (_hb_glyph_info_ligated (&info)) return false;
+  return !!(FLAG_UNSAFE (info.indic_category()) & flags);
+}
+
+static inline bool
+is_joiner (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, JOINER_FLAGS);
+}
+
+static inline bool
+is_consonant (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, CONSONANT_FLAGS);
+}
+
+static inline bool
+is_halant (const hb_glyph_info_t &info)
+{
+  return is_one_of (info, FLAG (OT_H));
+}
+
+#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
+
+#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
+#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
+#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
+#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
+#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
+#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
+#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
+#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
+#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
+#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
+
+
+#define MATRA_POS_LEFT(u)       POS_PRE_M
+#define MATRA_POS_RIGHT(u)      ( \
+                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                  IS_BENG(u) ? POS_AFTER_POST : \
+                                  IS_GURU(u) ? POS_AFTER_POST : \
+                                  IS_GUJR(u) ? POS_AFTER_POST : \
+                                  IS_ORYA(u) ? POS_AFTER_POST : \
+                                  IS_TAML(u) ? POS_AFTER_POST : \
+                                  IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+                                  IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
+                                  IS_MLYM(u) ? POS_AFTER_POST : \
+                                  IS_SINH(u) ? POS_AFTER_SUB  : \
+                                  /*default*/  POS_AFTER_SUB    \
+                                )
+#define MATRA_POS_TOP(u)        ( /* BENG and MLYM don't have top matras. */ \
+                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                  IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
+                                  IS_GUJR(u) ? POS_AFTER_SUB  : \
+                                  IS_ORYA(u) ? POS_AFTER_MAIN : \
+                                  IS_TAML(u) ? POS_AFTER_SUB  : \
+                                  IS_TELU(u) ? POS_BEFORE_SUB : \
+                                  IS_KNDA(u) ? POS_BEFORE_SUB : \
+                                  IS_SINH(u) ? POS_AFTER_SUB  : \
+                                  /*default*/  POS_AFTER_SUB    \
+                                )
+#define MATRA_POS_BOTTOM(u)     ( \
+                                  IS_DEVA(u) ? POS_AFTER_SUB  : \
+                                  IS_BENG(u) ? POS_AFTER_SUB  : \
+                                  IS_GURU(u) ? POS_AFTER_POST : \
+                                  IS_GUJR(u) ? POS_AFTER_POST : \
+                                  IS_ORYA(u) ? POS_AFTER_SUB  : \
+                                  IS_TAML(u) ? POS_AFTER_POST : \
+                                  IS_TELU(u) ? POS_BEFORE_SUB : \
+                                  IS_KNDA(u) ? POS_BEFORE_SUB : \
+                                  IS_MLYM(u) ? POS_AFTER_POST : \
+                                  IS_SINH(u) ? POS_AFTER_SUB  : \
+                                  /*default*/  POS_AFTER_SUB    \
+                                )
+
+static inline indic_position_t
+matra_position_indic (hb_codepoint_t u, indic_position_t side)
+{
+  switch ((int) side)
+  {
+    case POS_PRE_C:     return MATRA_POS_LEFT (u);
+    case POS_POST_C:    return MATRA_POS_RIGHT (u);
+    case POS_ABOVE_C:   return MATRA_POS_TOP (u);
+    case POS_BELOW_C:   return MATRA_POS_BOTTOM (u);
+  };
+  return side;
+}
+
+/* XXX
+ * This is a hack for now.  We should move this data into the main Indic table.
+ * Or completely remove it and just check in the tables.
+ */
+static const hb_codepoint_t ra_chars[] = {
+  0x0930u, /* Devanagari */
+  0x09B0u, /* Bengali */
+  0x09F0u, /* Bengali */
+  0x0A30u, /* Gurmukhi */       /* No Reph */
+  0x0AB0u, /* Gujarati */
+  0x0B30u, /* Oriya */
+  0x0BB0u, /* Tamil */          /* No Reph */
+  0x0C30u, /* Telugu */         /* Reph formed only with ZWJ */
+  0x0CB0u, /* Kannada */
+  0x0D30u, /* Malayalam */      /* No Reph, Logical Repha */
+
+  0x0DBBu, /* Sinhala */        /* Reph formed only with ZWJ */
+
+  0x179Au, /* Khmer */
+};
+
+static inline bool
+is_ra (hb_codepoint_t u)
+{
+  for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++)
+    if (u == ra_chars[i])
+      return true;
+  return false;
+}
+
+static inline void
+set_indic_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+
+  /*
+   * Re-assign category
+   */
+
+  /* The following act more like the Bindus. */
+  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
+    cat = OT_SM;
+  /* The following act like consonants. */
+  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
+                                      0x1CF5u, 0x1CF6u)))
+    cat = OT_C;
+  /* TODO: The following should only be allowed after a Visarga.
+   * For now, just treat them like regular tone marks. */
+  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
+    cat = OT_A;
+  /* TODO: The following should only be allowed after some of
+   * the nasalization marks, maybe only for U+1CE9..U+1CF1.
+   * For now, just treat them like tone marks. */
+  else if (unlikely (u == 0x1CEDu))
+    cat = OT_A;
+  /* The following take marks in standalone clusters, similar to Avagraha. */
+  else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
+                                      0x1CE9u, 0x1CECu,
+                                      0x1CEEu, 0x1CF1u)))
+  {
+    cat = OT_Symbol;
+    static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
+  }
+  else if (unlikely (u == 0x0A51u))
+  {
+    /* https://github.com/harfbuzz/harfbuzz/issues/524 */
+    cat = OT_M;
+    pos = POS_BELOW_C;
+  }
+
+  /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
+   * so the Indic shaper needs to know their categories. */
+  else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
+  else if (unlikely (u == 0x1133cu)) cat = OT_N;
+
+  else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
+
+  else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
+  else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
+  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
+                                    cat = OT_PLACEHOLDER;
+  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
+
+
+  /*
+   * Re-assign position.
+   */
+
+  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
+  {
+    pos = POS_BASE_C;
+    if (is_ra (u))
+      cat = OT_Ra;
+  }
+  else if (cat == OT_M)
+  {
+    pos = matra_position_indic (u, pos);
+  }
+  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
+  {
+    pos = POS_SMVD;
+  }
+
+  if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
+
+
+
+  info.indic_category() = cat;
+  info.indic_position() = pos;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-machine.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-machine.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,143 +29,212 @@
 #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-khmer-machine.hh"
 static const unsigned char _khmer_syllable_machine_trans_keys[] = {
-        7u, 7u, 1u, 16u, 13u, 13u, 1u, 16u, 7u, 13u, 7u, 7u, 1u, 16u, 13u, 13u,
-        1u, 16u, 7u, 13u, 1u, 16u, 3u, 14u, 3u, 14u, 5u, 14u, 3u, 14u, 5u, 14u,
-        8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u, 3u, 14u, 5u, 14u,
-        3u, 14u, 5u, 14u, 8u, 8u, 3u, 13u, 3u, 8u, 8u, 8u, 3u, 8u, 3u, 14u,
-        3u, 14u, 7u, 13u, 7u, 7u, 1u, 16u, 0
+        5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u,
+        5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u,
+        5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 16u, 1u, 29u, 5u, 29u,
+        5u, 29u, 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 5u, 26u,
+        5u, 29u, 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u,
+        5u, 29u, 0
 };
 
 static const char _khmer_syllable_machine_key_spans[] = {
-        1, 16, 1, 16, 7, 1, 16, 1,
-        16, 7, 16, 12, 12, 10, 12, 10,
-        1, 11, 6, 1, 6, 12, 12, 10,
-        12, 10, 1, 11, 6, 1, 6, 12,
-        12, 7, 1, 16
+        22, 17, 22, 17, 16, 17, 22, 17,
+        22, 17, 16, 17, 22, 17, 16, 17,
+        22, 17, 22, 17, 22, 16, 29, 25,
+        25, 25, 1, 18, 25, 25, 25, 22,
+        25, 25, 1, 18, 25, 25, 16, 25,
+        25
 };
 
 static const short _khmer_syllable_machine_index_offsets[] = {
-        0, 2, 19, 21, 38, 46, 48, 65,
-        67, 84, 92, 109, 122, 135, 146, 159,
-        170, 172, 184, 191, 193, 200, 213, 226,
-        237, 250, 261, 263, 275, 282, 284, 291,
-        304, 317, 325, 327
+        0, 23, 41, 64, 82, 99, 117, 140,
+        158, 181, 199, 216, 234, 257, 275, 292,
+        310, 333, 351, 374, 392, 415, 432, 462,
+        488, 514, 540, 542, 561, 587, 613, 639,
+        662, 688, 714, 716, 735, 761, 787, 804,
+        830
 };
 
 static const char _khmer_syllable_machine_indicies[] = {
-        1, 0, 2, 2, 0, 0, 0, 0,
+        1, 1, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 2,
+        3, 0, 0, 0, 0, 4, 0, 1,
+        1, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 3,
+        0, 1, 1, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 3, 0, 0, 0, 0, 4, 0,
+        5, 5, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        4, 0, 6, 6, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 2, 0, 3, 0, 4, 4, 0,
+        0, 6, 0, 7, 7, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 8, 0, 9, 9, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 10, 0, 0,
+        0, 0, 4, 0, 9, 9, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 10, 0, 11, 11,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 12, 0,
+        0, 0, 0, 4, 0, 11, 11, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0, 4, 0, 1, 0,
-        0, 0, 0, 0, 5, 0, 7, 6,
-        8, 8, 6, 6, 6, 6, 6, 6,
-        6, 6, 6, 6, 6, 6, 6, 8,
-        6, 9, 6, 10, 10, 6, 6, 6,
-        6, 6, 6, 6, 6, 6, 6, 6,
-        6, 6, 10, 6, 7, 6, 6, 6,
-        6, 6, 11, 6, 4, 4, 13, 12,
-        14, 15, 7, 16, 12, 12, 4, 4,
-        11, 17, 12, 4, 12, 19, 18, 20,
-        21, 1, 22, 18, 18, 18, 18, 5,
-        23, 18, 24, 18, 21, 21, 1, 22,
-        18, 18, 18, 18, 18, 23, 18, 21,
-        21, 1, 22, 18, 18, 18, 18, 18,
-        23, 18, 25, 18, 21, 21, 1, 22,
-        18, 18, 18, 18, 18, 26, 18, 21,
-        21, 1, 22, 18, 18, 18, 18, 18,
-        26, 18, 27, 18, 28, 18, 29, 18,
-        18, 22, 18, 18, 18, 18, 3, 18,
-        30, 18, 18, 18, 18, 22, 18, 22,
-        18, 28, 18, 18, 18, 18, 22, 18,
-        19, 18, 21, 21, 1, 22, 18, 18,
-        18, 18, 18, 23, 18, 32, 31, 33,
-        33, 7, 16, 31, 31, 31, 31, 31,
-        34, 31, 33, 33, 7, 16, 31, 31,
-        31, 31, 31, 34, 31, 35, 31, 33,
-        33, 7, 16, 31, 31, 31, 31, 31,
-        36, 31, 33, 33, 7, 16, 31, 31,
-        31, 31, 31, 36, 31, 37, 31, 38,
-        31, 39, 31, 31, 16, 31, 31, 31,
-        31, 9, 31, 40, 31, 31, 31, 31,
-        16, 31, 16, 31, 38, 31, 31, 31,
-        31, 16, 31, 13, 31, 41, 33, 7,
-        16, 31, 31, 31, 31, 11, 34, 31,
-        13, 31, 33, 33, 7, 16, 31, 31,
-        31, 31, 31, 34, 31, 7, 42, 42,
-        42, 42, 42, 11, 42, 7, 42, 10,
-        10, 42, 42, 42, 42, 42, 42, 42,
-        42, 42, 42, 42, 42, 42, 10, 42,
+        0, 0, 0, 0, 0, 12, 0, 13,
+        13, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 13, 0,
+        15, 15, 14, 14, 14, 14, 14, 14,
+        14, 14, 14, 14, 14, 14, 14, 14,
+        16, 14, 15, 15, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 16, 17, 17, 17, 17, 18,
+        17, 19, 19, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 18, 17, 20, 20, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 20, 17, 21, 21, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 22, 17, 23, 23,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 24, 17,
+        17, 17, 17, 18, 17, 23, 23, 17,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 24, 17, 25,
+        25, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 26,
+        17, 17, 17, 17, 18, 17, 25, 25,
+        17, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 26, 17,
+        15, 15, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 17, 27,
+        16, 17, 17, 17, 17, 18, 17, 28,
+        28, 17, 17, 17, 17, 17, 17, 17,
+        17, 17, 17, 17, 17, 17, 28, 17,
+        13, 13, 29, 29, 30, 30, 29, 29,
+        29, 29, 2, 2, 29, 31, 29, 13,
+        29, 29, 29, 29, 16, 20, 29, 29,
+        29, 18, 24, 26, 22, 29, 33, 33,
+        32, 32, 32, 32, 32, 32, 32, 34,
+        32, 32, 32, 32, 32, 2, 3, 6,
+        32, 32, 32, 4, 10, 12, 8, 32,
+        35, 35, 32, 32, 32, 32, 32, 32,
+        32, 36, 32, 32, 32, 32, 32, 32,
+        3, 6, 32, 32, 32, 4, 10, 12,
+        8, 32, 5, 5, 32, 32, 32, 32,
+        32, 32, 32, 36, 32, 32, 32, 32,
+        32, 32, 4, 6, 32, 32, 32, 32,
+        32, 32, 8, 32, 6, 32, 7, 7,
+        32, 32, 32, 32, 32, 32, 32, 36,
+        32, 32, 32, 32, 32, 32, 8, 6,
+        32, 37, 37, 32, 32, 32, 32, 32,
+        32, 32, 36, 32, 32, 32, 32, 32,
+        32, 10, 6, 32, 32, 32, 4, 32,
+        32, 8, 32, 38, 38, 32, 32, 32,
+        32, 32, 32, 32, 36, 32, 32, 32,
+        32, 32, 32, 12, 6, 32, 32, 32,
+        4, 10, 32, 8, 32, 35, 35, 32,
+        32, 32, 32, 32, 32, 32, 34, 32,
+        32, 32, 32, 32, 32, 3, 6, 32,
+        32, 32, 4, 10, 12, 8, 32, 15,
+        15, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 16,
+        39, 39, 39, 39, 18, 39, 41, 41,
+        40, 40, 40, 40, 40, 40, 40, 42,
+        40, 40, 40, 40, 40, 40, 16, 20,
+        40, 40, 40, 18, 24, 26, 22, 40,
+        19, 19, 40, 40, 40, 40, 40, 40,
+        40, 42, 40, 40, 40, 40, 40, 40,
+        18, 20, 40, 40, 40, 40, 40, 40,
+        22, 40, 20, 40, 21, 21, 40, 40,
+        40, 40, 40, 40, 40, 42, 40, 40,
+        40, 40, 40, 40, 22, 20, 40, 43,
+        43, 40, 40, 40, 40, 40, 40, 40,
+        42, 40, 40, 40, 40, 40, 40, 24,
+        20, 40, 40, 40, 18, 40, 40, 22,
+        40, 44, 44, 40, 40, 40, 40, 40,
+        40, 40, 42, 40, 40, 40, 40, 40,
+        40, 26, 20, 40, 40, 40, 18, 24,
+        40, 22, 40, 28, 28, 39, 39, 39,
+        39, 39, 39, 39, 39, 39, 39, 39,
+        39, 39, 28, 39, 45, 45, 40, 40,
+        40, 40, 40, 40, 40, 46, 40, 40,
+        40, 40, 40, 27, 16, 20, 40, 40,
+        40, 18, 24, 26, 22, 40, 41, 41,
+        40, 40, 40, 40, 40, 40, 40, 46,
+        40, 40, 40, 40, 40, 40, 16, 20,
+        40, 40, 40, 18, 24, 26, 22, 40,
         0
 };
 
 static const char _khmer_syllable_machine_trans_targs[] = {
-        10, 14, 17, 20, 11, 21, 10, 24,
-        27, 30, 31, 32, 10, 22, 33, 34,
-        26, 35, 10, 12, 4, 0, 16, 3,
-        13, 15, 1, 10, 18, 2, 19, 10,
-        23, 5, 8, 25, 6, 10, 28, 7,
-        29, 9, 10
+        22, 1, 30, 24, 25, 3, 26, 5,
+        27, 7, 28, 9, 29, 23, 22, 11,
+        32, 22, 33, 13, 34, 15, 35, 17,
+        36, 19, 37, 40, 39, 22, 31, 38,
+        22, 0, 10, 2, 4, 6, 8, 22,
+        22, 12, 14, 16, 18, 20, 21
 };
 
 static const char _khmer_syllable_machine_trans_actions[] = {
-        1, 2, 2, 0, 2, 2, 3, 2,
-        2, 0, 2, 2, 6, 2, 0, 0,
-        0, 0, 7, 2, 0, 0, 0, 0,
-        2, 2, 0, 8, 0, 0, 0, 9,
-        2, 0, 0, 2, 0, 10, 0, 0,
-        0, 0, 11
+        1, 0, 2, 2, 2, 0, 0, 0,
+        2, 0, 2, 0, 2, 2, 3, 0,
+        4, 5, 2, 0, 0, 0, 2, 0,
+        2, 0, 2, 4, 4, 8, 9, 0,
+        10, 0, 0, 0, 0, 0, 0, 11,
+        12, 0, 0, 0, 0, 0, 0
 };
 
 static const char _khmer_syllable_machine_to_state_actions[] = {
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 4, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 6, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0
+        0
 };
 
 static const char _khmer_syllable_machine_from_state_actions[] = {
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 5, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 7, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0, 0, 0, 0
+        0
 };
 
 static const unsigned char _khmer_syllable_machine_eof_trans[] = {
-        1, 1, 1, 1, 1, 7, 7, 7,
-        7, 7, 0, 19, 19, 19, 19, 19,
-        19, 19, 19, 19, 19, 19, 32, 32,
-        32, 32, 32, 32, 32, 32, 32, 32,
-        32, 43, 43, 43
+        1, 1, 1, 1, 1, 1, 1, 1,
+        1, 1, 1, 15, 18, 18, 18, 18,
+        18, 18, 18, 18, 18, 18, 0, 33,
+        33, 33, 33, 33, 33, 33, 33, 40,
+        41, 41, 41, 41, 41, 41, 40, 41,
+        41
 };
 
-static const int khmer_syllable_machine_start = 10;
-static const int khmer_syllable_machine_first_final = 10;
+static const int khmer_syllable_machine_start = 22;
+static const int khmer_syllable_machine_first_final = 22;
 static const int khmer_syllable_machine_error = -1;
 
-static const int khmer_syllable_machine_en_main = 10;
+static const int khmer_syllable_machine_en_main = 22;
 
 
 #line 36 "hb-ot-shape-complex-khmer-machine.rl"
 
 
 
-#line 74 "hb-ot-shape-complex-khmer-machine.rl"
+#line 80 "hb-ot-shape-complex-khmer-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -173,11 +242,11 @@
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 181 "hb-ot-shape-complex-khmer-machine.hh"
+#line 250 "hb-ot-shape-complex-khmer-machine.hh"
         {
         cs = khmer_syllable_machine_start;
         ts = 0;
@@ -185,16 +254,15 @@
         act = 0;
         }
 
-#line 95 "hb-ot-shape-complex-khmer-machine.rl"
+#line 100 "hb-ot-shape-complex-khmer-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
 
-#line 198 "hb-ot-shape-complex-khmer-machine.hh"
+#line 266 "hb-ot-shape-complex-khmer-machine.hh"
         {
         int _slen;
         int _trans;
@@ -204,11 +272,11 @@
                 goto _test_eof;
 _resume:
         switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
-        case 5:
+        case 7:
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 212 "hb-ot-shape-complex-khmer-machine.hh"
+#line 280 "hb-ot-shape-complex-khmer-machine.hh"
         }
 
         _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
@@ -231,47 +299,63 @@
         {te = p+1;}
         break;
         case 8:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
-        {te = p+1;{ found_syllable (consonant_syllable); }}
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
+        {te = p+1;{ found_syllable (non_khmer_cluster); }}
         break;
         case 10:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
-        {te = p+1;{ found_syllable (broken_cluster); }}
-        break;
-        case 6:
-#line 70 "hb-ot-shape-complex-khmer-machine.rl"
-        {te = p+1;{ found_syllable (non_khmer_cluster); }}
-        break;
-        case 7:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
+#line 74 "hb-ot-shape-complex-khmer-machine.rl"
         {te = p;p--;{ found_syllable (consonant_syllable); }}
         break;
-        case 9:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
+        case 12:
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
         {te = p;p--;{ found_syllable (broken_cluster); }}
         break;
         case 11:
-#line 70 "hb-ot-shape-complex-khmer-machine.rl"
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
         {te = p;p--;{ found_syllable (non_khmer_cluster); }}
         break;
         case 1:
-#line 68 "hb-ot-shape-complex-khmer-machine.rl"
+#line 74 "hb-ot-shape-complex-khmer-machine.rl"
         {{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
         break;
+        case 5:
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
+        {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
+        break;
+        case 3:
+#line 1 "NONE"
+        {       switch( act ) {
+        case 2:
+        {{p = ((te))-1;} found_syllable (broken_cluster); }
+        break;
         case 3:
-#line 69 "hb-ot-shape-complex-khmer-machine.rl"
-        {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
+        {{p = ((te))-1;} found_syllable (non_khmer_cluster); }
+        break;
+        }
+        }
         break;
-#line 266 "hb-ot-shape-complex-khmer-machine.hh"
+        case 4:
+#line 1 "NONE"
+        {te = p+1;}
+#line 75 "hb-ot-shape-complex-khmer-machine.rl"
+        {act = 2;}
+        break;
+        case 9:
+#line 1 "NONE"
+        {te = p+1;}
+#line 76 "hb-ot-shape-complex-khmer-machine.rl"
+        {act = 3;}
+        break;
+#line 350 "hb-ot-shape-complex-khmer-machine.hh"
         }
 
 _again:
         switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
-        case 4:
+        case 6:
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 275 "hb-ot-shape-complex-khmer-machine.hh"
+#line 359 "hb-ot-shape-complex-khmer-machine.hh"
         }
 
         if ( ++p != pe )
@@ -287,7 +371,7 @@
 
         }
 
-#line 104 "hb-ot-shape-complex-khmer-machine.rl"
+#line 108 "hb-ot-shape-complex-khmer-machine.rl"
 
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-/* buffer var allocations */
-#define khmer_category() indic_category() /* khmer_category_t */
-#define khmer_position() indic_position() /* khmer_position_t */
-
-
-typedef indic_category_t khmer_category_t;
-typedef indic_position_t khmer_position_t;
-
-
-static inline khmer_position_t
-matra_position_khmer (khmer_position_t side)
-{
-  switch ((int) side)
-  {
-    case POS_PRE_C:
-      return POS_PRE_M;
-
-    case POS_POST_C:
-    case POS_ABOVE_C:
-    case POS_BELOW_C:
-      return POS_AFTER_POST;
-
-    default:
-      return side;
-  };
-}
-
-static inline bool
-is_consonant_or_vowel (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, CONSONANT_FLAGS | FLAG (OT_V));
-}
-
-static inline bool
-is_coeng (const hb_glyph_info_t &info)
-{
-  return is_one_of (info, FLAG (OT_Coeng));
-}
-
-static inline void
-set_khmer_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
-  khmer_position_t pos = (khmer_position_t) (type >> 8);
-
-
-  /*
-   * Re-assign category
-   */
-
-  if (unlikely (u == 0x17C6u)) cat = OT_N; /* Khmer Bindu doesn't like to be repositioned. */
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x17CDu, 0x17D1u) ||
-                     u == 0x17CBu || u == 0x17D3u || u == 0x17DDu)) /* Khmer Various signs */
-  {
-    /* These can occur mid-syllable (eg. before matras), even though Unicode marks them as Syllable_Modifier.
-     * https://github.com/roozbehp/unicode-data/issues/5 */
-    cat = OT_M;
-    pos = POS_ABOVE_C;
-  }
-  else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u))) cat = OT_PLACEHOLDER;
-  else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
-  /*
-   * Re-assign position.
-   */
-
-  if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
-  {
-    pos = POS_BASE_C;
-    if (u == 0x179Au)
-      cat = OT_Ra;
-  }
-  else if (cat == OT_M)
-  {
-    pos = matra_position_khmer (pos);
-  }
-  else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) | FLAG (OT_A) | FLAG (OT_Symbol))))
-  {
-    pos = POS_SMVD;
-  }
-
-  info.khmer_category() = cat;
-  info.khmer_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,42 +24,38 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-khmer-private.hh"
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-shape-complex-khmer.hh"
+#include "hb-ot-layout.hh"
 
 
 /*
  * Khmer shaper.
  */
 
-struct feature_list_t {
-  hb_tag_t tag;
-  hb_ot_map_feature_flags_t flags;
-};
-
-static const feature_list_t
+static const hb_ot_map_feature_t
 khmer_features[] =
 {
   /*
    * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
+   * These features are applied in order, one at a time, after reordering.
    */
-  {HB_TAG('p','r','e','f'), F_NONE},
-  {HB_TAG('b','l','w','f'), F_NONE},
-  {HB_TAG('a','b','v','f'), F_NONE},
-  {HB_TAG('p','s','t','f'), F_NONE},
-  {HB_TAG('c','f','a','r'), F_NONE},
+  {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
+  {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS},
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
-   * Default Bengali font in Windows for example has intermixed
-   * lookups for init,pres,abvs,blws features.
+   * These features are applied all at once after clearing syllables.
    */
-  {HB_TAG('p','r','e','s'), F_GLOBAL},
-  {HB_TAG('a','b','v','s'), F_GLOBAL},
-  {HB_TAG('b','l','w','s'), F_GLOBAL},
-  {HB_TAG('p','s','t','s'), F_GLOBAL},
-  /* Positioning features, though we don't care about the types. */
+  {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   {HB_TAG('d','i','s','t'), F_GLOBAL},
   {HB_TAG('a','b','v','m'), F_GLOBAL},
   {HB_TAG('b','l','w','m'), F_GLOBAL},
@@ -79,12 +75,13 @@
   _ABVS,
   _BLWS,
   _PSTS,
+
   _DIST,
   _ABVM,
   _BLWM,
 
   KHMER_NUM_FEATURES,
-  KHMER_BASIC_FEATURES = _PRES /* Don't forget to update this! */
+  KHMER_BASIC_FEATURES = _PRES, /* Don't forget to update this! */
 };
 
 static void
@@ -92,13 +89,9 @@
                  hb_font_t *font,
                  hb_buffer_t *buffer);
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                    hb_font_t *font,
-                    hb_buffer_t *buffer);
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                  hb_font_t *font,
-                  hb_buffer_t *buffer);
+reorder (const hb_ot_shape_plan_t *plan,
+         hb_font_t *font,
+         hb_buffer_t *buffer);
 static void
 clear_syllables (const hb_ot_shape_plan_t *plan,
                  hb_font_t *font,
@@ -111,46 +104,54 @@
 
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
+  map->add_gsub_pause (reorder);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  /* The Indic specs do not require ccmp, but we apply it here since if
-   * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-
+  /* Testing suggests that Uniscribe does NOT pause between basic
+   * features.  Test with KhmerUI.ttf and the following three
+   * sequences:
+   *
+   *   U+1789,U+17BC
+   *   U+1789,U+17D2,U+1789
+   *   U+1789,U+17D2,U+1789,U+17BC
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/974
+   */
+  map->enable_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
 
   unsigned int i = 0;
-  map->add_gsub_pause (initial_reordering);
-  for (; i < KHMER_BASIC_FEATURES; i++) {
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-    map->add_gsub_pause (nullptr);
-  }
-  map->add_gsub_pause (final_reordering);
-  for (; i < KHMER_NUM_FEATURES; i++) {
-    map->add_feature (khmer_features[i].tag, 1, khmer_features[i].flags | F_MANUAL_ZWJ | F_MANUAL_ZWNJ);
-  }
-
-  map->add_global_bool_feature (HB_TAG('c','a','l','t'));
-  map->add_global_bool_feature (HB_TAG('c','l','i','g'));
+  for (; i < KHMER_BASIC_FEATURES; i++)
+    map->add_feature (khmer_features[i]);
 
   map->add_gsub_pause (clear_syllables);
+
+  for (; i < KHMER_NUM_FEATURES; i++)
+    map->add_feature (khmer_features[i]);
 }
 
 static void
 override_features_khmer (hb_ot_shape_planner_t *plan)
 {
+  hb_ot_map_builder_t *map = &plan->map;
+
+  /* Khmer spec has 'clig' as part of required shaping features:
+   * "Apply feature 'clig' to form ligatures that are desired for
+   * typographical correctness.", hence in overrides... */
+  map->enable_feature (HB_TAG('c','l','i','g'));
+
   /* Uniscribe does not apply 'kern' in Khmer. */
   if (hb_options ().uniscribe_bug_compatible)
   {
-    plan->map.add_feature (HB_TAG('k','e','r','n'), 0, F_GLOBAL);
+    map->disable_feature (HB_TAG('k','e','r','n'));
   }
 
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  map->disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
 struct would_substitute_feature_t
 {
-  inline void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+  void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
   {
     zero_context = zero_context_;
     map->get_stage_lookups (0/*GSUB*/,
@@ -158,9 +159,9 @@
                             &lookups, &count);
   }
 
-  inline bool would_substitute (const hb_codepoint_t *glyphs,
-                                unsigned int          glyphs_count,
-                                hb_face_t            *face) const
+  bool would_substitute (const hb_codepoint_t *glyphs,
+                         unsigned int          glyphs_count,
+                         hb_face_t            *face) const
   {
     for (unsigned int i = 0; i < count; i++)
       if (hb_ot_layout_lookup_would_substitute_fast (face, lookups[i].index, glyphs, glyphs_count, zero_context))
@@ -176,9 +177,7 @@
 
 struct khmer_shape_plan_t
 {
-  ASSERT_POD ();
-
-  inline bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
+  bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
   {
     hb_codepoint_t glyph = virama_glyph;
     if (unlikely (virama_glyph == (hb_codepoint_t) -1))
@@ -243,7 +242,6 @@
                    hb_font_t                *font HB_UNUSED)
 {
   HB_BUFFER_ALLOCATE_VAR (buffer, khmer_category);
-  HB_BUFFER_ALLOCATE_VAR (buffer, khmer_position);
 
   /* We cannot setup masks here.  We save information about characters
    * and setup masks later on in a pause-callback. */
@@ -264,162 +262,58 @@
     buffer->unsafe_to_break (start, end);
 }
 
-static int
-compare_khmer_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
-  int a = pa->khmer_position();
-  int b = pb->khmer_position();
-
-  return a < b ? -1 : a == b ? 0 : +1;
-}
-
 
 /* Rules from:
  * https://docs.microsoft.com/en-us/typography/script-development/devanagari */
 
 static void
-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
-                                       hb_face_t *face,
-                                       hb_buffer_t *buffer,
-                                       unsigned int start, unsigned int end)
+reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
+                            hb_face_t *face HB_UNUSED,
+                            hb_buffer_t *buffer,
+                            unsigned int start, unsigned int end)
 {
   const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
   hb_glyph_info_t *info = buffer->info;
 
-  /* 1. Khmer shaping assumes that a syllable will begin with a Cons, IndV, or Number. */
-
-  /* The first consonant is always the base. */
-  unsigned int base = start;
-  info[base].khmer_position() = POS_BASE_C;
-
-  /* Mark all subsequent consonants as below. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (is_consonant_or_vowel (info[i]))
-      info[i].khmer_position() = POS_BELOW_C;
-
-  /* Mark final consonants.  A final consonant is one appearing after a matra,
-   * like in Khmer. */
-  for (unsigned int i = base + 1; i < end; i++)
-    if (info[i].khmer_category() == OT_M) {
-      for (unsigned int j = i + 1; j < end; j++)
-        if (is_consonant_or_vowel (info[j])) {
-          info[j].khmer_position() = POS_FINAL_C;
-          break;
-        }
-      break;
-    }
-
-  /* Attach misc marks to previous char to move with them. */
-  {
-    khmer_position_t last_pos = POS_START;
-    for (unsigned int i = start; i < end; i++)
-    {
-      if ((FLAG_UNSAFE (info[i].khmer_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_Coeng))))
-      {
-        info[i].khmer_position() = last_pos;
-        if (unlikely (info[i].khmer_category() == OT_Coeng &&
-                      info[i].khmer_position() == POS_PRE_M))
-        {
-          /*
-           * Uniscribe doesn't move the Halant with Left Matra.
-           * TEST: U+092B,U+093F,U+094DE
-           * We follow.  This is important for the Sinhala
-           * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
-           * where U+0DD9 is a left matra and U+0DCA is the virama.
-           * We don't want to move the virama with the left matra.
-           * TEST: U+0D9A,U+0DDA
-           */
-          for (unsigned int j = i; j > start; j--)
-            if (info[j - 1].khmer_position() != POS_PRE_M) {
-              info[i].khmer_position() = info[j - 1].khmer_position();
-              break;
-            }
-        }
-      } else if (info[i].khmer_position() != POS_SMVD) {
-        last_pos = (khmer_position_t) info[i].khmer_position();
-      }
-    }
-  }
-  /* For post-base consonants let them own anything before them
-   * since the last consonant or matra. */
+  /* Setup masks. */
   {
-    unsigned int last = base;
-    for (unsigned int i = base + 1; i < end; i++)
-      if (is_consonant_or_vowel (info[i]))
-      {
-        for (unsigned int j = last + 1; j < i; j++)
-          if (info[j].khmer_position() < POS_SMVD)
-            info[j].khmer_position() = info[i].khmer_position();
-        last = i;
-      } else if (info[i].khmer_category() == OT_M)
-        last = i;
-  }
-
-  {
-    /* Use syllable() for sort accounting temporarily. */
-    unsigned int syllable = info[start].syllable();
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = i - start;
-
-    /* Sit tight, rock 'n roll! */
-    hb_stable_sort (info + start, end - start, compare_khmer_order);
-    /* Find base again */
-    base = end;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].khmer_position() == POS_BASE_C)
-      {
-        base = i;
-        break;
-      }
-
-    if (unlikely (end - start >= 127))
-      buffer->merge_clusters (start, end);
-    else
-      /* Note!  syllable() is a one-byte field. */
-      for (unsigned int i = base; i < end; i++)
-        if (info[i].syllable() != 255)
-        {
-          unsigned int max = i;
-          unsigned int j = start + info[i].syllable();
-          while (j != i)
-          {
-            max = MAX (max, j);
-            unsigned int next = start + info[j].syllable();
-            info[j].syllable() = 255; /* So we don't process j later again. */
-            j = next;
-          }
-          if (i != max)
-            buffer->merge_clusters (i, max + 1);
-        }
-
-    /* Put syllable back in. */
-    for (unsigned int i = start; i < end; i++)
-      info[i].syllable() = syllable;
-  }
-
-  /* Setup masks now */
-
-  {
-    hb_mask_t mask;
-
     /* Post-base */
-    mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
-    for (unsigned int i = base + 1; i < end; i++)
+    hb_mask_t mask = khmer_plan->mask_array[BLWF] | khmer_plan->mask_array[ABVF] | khmer_plan->mask_array[PSTF];
+    for (unsigned int i = start + 1; i < end; i++)
       info[i].mask  |= mask;
   }
 
-  unsigned int pref_len = 2;
-  if (khmer_plan->mask_array[PREF] && base + pref_len < end)
+  unsigned int num_coengs = 0;
+  for (unsigned int i = start + 1; i < end; i++)
   {
-    /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
-    for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
-      hb_codepoint_t glyphs[2];
-      for (unsigned int j = 0; j < pref_len; j++)
-        glyphs[j] = info[i + j].codepoint;
-      if (khmer_plan->pref.would_substitute (glyphs, pref_len, face))
+    /* """
+     * When a COENG + (Cons | IndV) combination are found (and subscript count
+     * is less than two) the character combination is handled according to the
+     * subscript type of the character following the COENG.
+     *
+     * ...
+     *
+     * Subscript Type 2 - The COENG + RO characters are reordered to immediately
+     * before the base glyph. Then the COENG + RO characters are assigned to have
+     * the 'pref' OpenType feature applied to them.
+     * """
+     */
+    if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end)
+    {
+      num_coengs++;
+
+      if (info[i + 1].khmer_category() == OT_Ra)
       {
-        for (unsigned int j = 0; j < pref_len; j++)
-          info[i++].mask |= khmer_plan->mask_array[PREF];
+        for (unsigned int j = 0; j < 2; j++)
+          info[i + j].mask |= khmer_plan->mask_array[PREF];
+
+        /* Move the Coeng,Ro sequence to the start. */
+        buffer->merge_clusters (start, i + 2);
+        hb_glyph_info_t t0 = info[i];
+        hb_glyph_info_t t1 = info[i + 1];
+        memmove (&info[start + 2], &info[start], (i - start) * sizeof (info[0]));
+        info[start] = t0;
+        info[start + 1] = t1;
 
         /* Mark the subsequent stuff with 'cfar'.  Used in Khmer.
          * Read the feature spec.
@@ -428,11 +322,21 @@
          * U+1784,U+17D2,U+1782,U+17D2,U+179A
          */
         if (khmer_plan->mask_array[CFAR])
-          for (; i < end; i++)
-            info[i].mask |= khmer_plan->mask_array[CFAR];
+          for (unsigned int j = i + 2; j < end; j++)
+            info[j].mask |= khmer_plan->mask_array[CFAR];
+
+        num_coengs = 2; /* Done. */
+      }
+    }
 
-        break;
-      }
+    /* Reorder left matra piece. */
+    else if (info[i].khmer_category() == OT_VPre)
+    {
+      /* Move to the start. */
+      buffer->merge_clusters (start, i + 1);
+      hb_glyph_info_t t = info[i];
+      memmove (&info[start + 1], &info[start], (i - start) * sizeof (info[0]));
+      info[start] = t;
     }
   }
 }
@@ -448,7 +352,7 @@
   {
     case broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
     case consonant_syllable:
-     initial_reordering_consonant_syllable (plan, face, buffer, start, end);
+     reorder_consonant_syllable (plan, face, buffer, start, end);
      break;
 
     case non_khmer_cluster:
@@ -513,263 +417,22 @@
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                    hb_font_t *font,
-                    hb_buffer_t *buffer)
+reorder (const hb_ot_shape_plan_t *plan,
+         hb_font_t *font,
+         hb_buffer_t *buffer)
 {
   insert_dotted_circles (plan, font, buffer);
 
   foreach_syllable (buffer, start, end)
     initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering_syllable (const hb_ot_shape_plan_t *plan,
-                           hb_buffer_t *buffer,
-                           unsigned int start, unsigned int end)
-{
-  const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
-  hb_glyph_info_t *info = buffer->info;
-
-
-  /* This function relies heavily on halant glyphs.  Lots of ligation
-   * and possibly multiple substitutions happened prior to this
-   * phase, and that might have messed up our properties.  Recover
-   * from a particular case of that where we're fairly sure that a
-   * class of OT_Coeng is desired but has been lost. */
-  if (khmer_plan->virama_glyph)
-  {
-    unsigned int virama_glyph = khmer_plan->virama_glyph;
-    for (unsigned int i = start; i < end; i++)
-      if (info[i].codepoint == virama_glyph &&
-          _hb_glyph_info_ligated (&info[i]) &&
-          _hb_glyph_info_multiplied (&info[i]))
-      {
-        /* This will make sure that this glyph passes is_coeng() test. */
-        info[i].khmer_category() = OT_Coeng;
-        _hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
-      }
-  }
-
-
-  /* 4. Final reordering:
-   *
-   * After the localized forms and basic shaping forms GSUB features have been
-   * applied (see below), the shaping engine performs some final glyph
-   * reordering before applying all the remaining font features to the entire
-   * syllable.
-   */
-
-  bool try_pref = !!khmer_plan->mask_array[PREF];
-
-  /* Find base again */
-  unsigned int base;
-  for (base = start; base < end; base++)
-    if (info[base].khmer_position() >= POS_BASE_C)
-    {
-      if (try_pref && base + 1 < end)
-      {
-        for (unsigned int i = base + 1; i < end; i++)
-          if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
-          {
-            if (!(_hb_glyph_info_substituted (&info[i]) &&
-                  _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
-            {
-              /* Ok, this was a 'pref' candidate but didn't form any.
-               * Base is around here... */
-              base = i;
-              while (base < end && is_coeng (info[base]))
-                base++;
-              info[base].khmer_position() = POS_BASE_C;
-
-              try_pref = false;
-            }
-            break;
-          }
-      }
-
-      if (start < base && info[base].khmer_position() > POS_BASE_C)
-        base--;
-      break;
-    }
-  if (base == end && start < base &&
-      is_one_of (info[base - 1], FLAG (OT_ZWJ)))
-    base--;
-  if (base < end)
-    while (start < base &&
-           is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_Coeng))))
-      base--;
-
-
-  /*   o Reorder matras:
-   *
-   *     If a pre-base matra character had been reordered before applying basic
-   *     features, the glyph can be moved closer to the main consonant based on
-   *     whether half-forms had been formed. Actual position for the matra is
-   *     defined as “after last standalone halant glyph, after initial matra
-   *     position and before the main consonant”. If ZWJ or ZWNJ follow this
-   *     halant, position is moved after it.
-   */
-
-  if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
-  {
-    /* If we lost track of base, alas, position before last thingy. */
-    unsigned int new_pos = base == end ? base - 2 : base - 1;
-
-    while (new_pos > start &&
-           !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_Coeng)))))
-      new_pos--;
-
-    /* If we found no Halant we are done.
-     * Otherwise only proceed if the Halant does
-     * not belong to the Matra itself! */
-    if (is_coeng (info[new_pos]) &&
-        info[new_pos].khmer_position() != POS_PRE_M)
-    {
-      /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-      if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
-        new_pos++;
-    }
-    else
-      new_pos = start; /* No move. */
-
-    if (start < new_pos && info[new_pos].khmer_position () != POS_PRE_M)
-    {
-      /* Now go see if there's actually any matras... */
-      for (unsigned int i = new_pos; i > start; i--)
-        if (info[i - 1].khmer_position () == POS_PRE_M)
-        {
-          unsigned int old_pos = i - 1;
-          if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
-            base--;
-
-          hb_glyph_info_t tmp = info[old_pos];
-          memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
-          info[new_pos] = tmp;
-
-          /* Note: this merge_clusters() is intentionally *after* the reordering.
-           * Indic matra reordering is special and tricky... */
-          buffer->merge_clusters (new_pos, MIN (end, base + 1));
-
-          new_pos--;
-        }
-    } else {
-      for (unsigned int i = start; i < base; i++)
-        if (info[i].khmer_position () == POS_PRE_M) {
-          buffer->merge_clusters (i, MIN (end, base + 1));
-          break;
-        }
-    }
-  }
-
-
-  /*   o Reorder pre-base-reordering consonants:
-   *
-   *     If a pre-base-reordering consonant is found, reorder it according to
-   *     the following rules:
-   */
-
-  if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
-  {
-    for (unsigned int i = base + 1; i < end; i++)
-      if ((info[i].mask & khmer_plan->mask_array[PREF]) != 0)
-      {
-        /*       1. Only reorder a glyph produced by substitution during application
-         *          of the <pref> feature. (Note that a font may shape a Ra consonant with
-         *          the feature generally but block it in certain contexts.)
-         */
-        /* Note: We just check that something got substituted.  We don't check that
-         * the <pref> feature actually did it...
-         *
-         * Reorder pref only if it ligated. */
-        if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
-        {
-          /*
-           *       2. Try to find a target position the same way as for pre-base matra.
-           *          If it is found, reorder pre-base consonant glyph.
-           *
-           *       3. If position is not found, reorder immediately before main
-           *          consonant.
-           */
-
-          unsigned int new_pos = base;
-          while (new_pos > start &&
-                 !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_Coeng))))
-            new_pos--;
-
-          /* In Khmer coeng model, a H,Ra can go *after* matras.  If it goes after a
-           * split matra, it should be reordered to *before* the left part of such matra. */
-          if (new_pos > start && info[new_pos - 1].khmer_category() == OT_M)
-          {
-            unsigned int old_pos = i;
-            for (unsigned int j = base + 1; j < old_pos; j++)
-              if (info[j].khmer_category() == OT_M)
-              {
-                new_pos--;
-                break;
-              }
-          }
-
-          if (new_pos > start && is_coeng (info[new_pos - 1]))
-          {
-            /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
-            if (new_pos < end && is_joiner (info[new_pos]))
-              new_pos++;
-          }
-
-          {
-            unsigned int old_pos = i;
-
-            buffer->merge_clusters (new_pos, old_pos + 1);
-            hb_glyph_info_t tmp = info[old_pos];
-            memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
-            info[new_pos] = tmp;
-
-            if (new_pos <= base && base < old_pos)
-              base++;
-          }
-        }
-
-        break;
-      }
-  }
-
-
-  /*
-   * Finish off the clusters and go home!
-   */
-  if (hb_options ().uniscribe_bug_compatible)
-  {
-    /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
-     * This means, half forms are submerged into the main consonant's cluster.
-     * This is unnecessary, and makes cursor positioning harder, but that's what
-     * Uniscribe does. */
-    buffer->merge_clusters (start, end);
-  }
-}
-
-
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                  hb_font_t *font HB_UNUSED,
-                  hb_buffer_t *buffer)
-{
-  unsigned int count = buffer->len;
-  if (unlikely (!count)) return;
-
-  foreach_syllable (buffer, start, end)
-    final_reordering_syllable (plan, buffer, start, end);
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
-  HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_position);
 }
 
-
 static void
 clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
                  hb_font_t *font HB_UNUSED,
@@ -831,7 +494,7 @@
   decompose_khmer,
   compose_khmer,
   setup_masks_khmer,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
   false, /* fallback_position */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-khmer.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_KHMER_HH
+#define HB_OT_SHAPE_COMPLEX_KHMER_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex-indic.hh"
+
+
+/* buffer var allocations */
+#define khmer_category() indic_category() /* khmer_category_t */
+
+
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum khmer_category_t
+{
+  OT_Robatic = 20,
+  OT_Xgroup  = 21,
+  OT_Ygroup  = 22,
+
+  OT_VAbv    = 26,
+  OT_VBlw    = 27,
+  OT_VPre    = 28,
+  OT_VPst    = 29,
+};
+
+static inline void
+set_khmer_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  khmer_category_t cat = (khmer_category_t) (type & 0x7Fu);
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+
+  /*
+   * Re-assign category
+   *
+   * These categories are experimentally extracted from what Uniscribe allows.
+   */
+  switch (u)
+  {
+    case 0x179Au:
+      cat = (khmer_category_t) OT_Ra;
+      break;
+
+    case 0x17CCu:
+    case 0x17C9u:
+    case 0x17CAu:
+      cat = OT_Robatic;
+      break;
+
+    case 0x17C6u:
+    case 0x17CBu:
+    case 0x17CDu:
+    case 0x17CEu:
+    case 0x17CFu:
+    case 0x17D0u:
+    case 0x17D1u:
+      cat = OT_Xgroup;
+      break;
+
+    case 0x17C7u:
+    case 0x17C8u:
+    case 0x17DDu:
+    case 0x17D3u: /* Just guessing. Uniscribe doesn't categorize it. */
+      cat = OT_Ygroup;
+      break;
+  }
+
+  /*
+   * Re-assign position.
+   */
+  if (cat == (khmer_category_t) OT_M)
+    switch ((int) pos)
+    {
+      case POS_PRE_C:   cat = OT_VPre; break;
+      case POS_BELOW_C: cat = OT_VBlw; break;
+      case POS_ABOVE_C: cat = OT_VAbv; break;
+      case POS_POST_C:  cat = OT_VPst; break;
+      default: assert (0);
+    };
+
+  info.khmer_category() = cat;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_KHMER_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-machine.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-machine.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,7 +29,7 @@
 #ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 36 "hb-ot-shape-complex-myanmar-machine.hh"
@@ -283,10 +283,9 @@
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -294,11 +293,11 @@
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te HB_UNUSED, act HB_UNUSED;
+  unsigned int p, pe, eof, ts, te, act HB_UNUSED;
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 302 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 301 "hb-ot-shape-complex-myanmar-machine.hh"
         {
         cs = myanmar_syllable_machine_start;
         ts = 0;
@@ -306,16 +305,15 @@
         act = 0;
         }
 
-#line 115 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 114 "hb-ot-shape-complex-myanmar-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
 
-#line 319 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 317 "hb-ot-shape-complex-myanmar-machine.hh"
         {
         int _slen;
         int _trans;
@@ -329,7 +327,7 @@
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 333 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 331 "hb-ot-shape-complex-myanmar-machine.hh"
         }
 
         _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
@@ -379,7 +377,7 @@
 #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
         {te = p;p--;{ found_syllable (non_myanmar_cluster); }}
         break;
-#line 383 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 381 "hb-ot-shape-complex-myanmar-machine.hh"
         }
 
 _again:
@@ -388,7 +386,7 @@
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 392 "hb-ot-shape-complex-myanmar-machine.hh"
+#line 390 "hb-ot-shape-complex-myanmar-machine.hh"
         }
 
         if ( ++p != pe )
@@ -404,7 +402,7 @@
 
         }
 
-#line 124 "hb-ot-shape-complex-myanmar-machine.rl"
+#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
 
 }
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-complex-indic-private.hh"
-
-
-/* buffer var allocations */
-#define myanmar_category() indic_category() /* myanmar_category_t */
-#define myanmar_position() indic_position() /* myanmar_position_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum myanmar_category_t {
-  OT_As  = 18,  /* Asat */
-  OT_D0  = 20, /* Digit zero */
-  OT_DB  = OT_N, /* Dot below */
-  OT_GB  = OT_PLACEHOLDER,
-  OT_MH  = 21, /* Various consonant medial types */
-  OT_MR  = 22, /* Various consonant medial types */
-  OT_MW  = 23, /* Various consonant medial types */
-  OT_MY  = 24, /* Various consonant medial types */
-  OT_PT  = 25, /* Pwo and other tones */
-  OT_VAbv = 26,
-  OT_VBlw = 27,
-  OT_VPre = 28,
-  OT_VPst = 29,
-  OT_VS   = 30, /* Variation selectors */
-  OT_P    = 31, /* Punctuation */
-  OT_D    = 32, /* Digits except zero */
-};
-
-
-static inline void
-set_myanmar_properties (hb_glyph_info_t &info)
-{
-  hb_codepoint_t u = info.codepoint;
-  unsigned int type = hb_indic_get_categories (u);
-  indic_category_t cat = (indic_category_t) (type & 0x7Fu);
-  indic_position_t pos = (indic_position_t) (type >> 8);
-
-  /* Myanmar
-   * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
-   */
-  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
-    cat = (indic_category_t) OT_VS;
-
-  switch (u)
-  {
-    case 0x104Eu:
-      cat = (indic_category_t) OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
-      break;
-
-    case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
-    case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
-    case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
-    case 0x25FEu:
-      cat = (indic_category_t) OT_GB;
-      break;
-
-    case 0x1004u: case 0x101Bu: case 0x105Au:
-      cat = (indic_category_t) OT_Ra;
-      break;
-
-    case 0x1032u: case 0x1036u:
-      cat = (indic_category_t) OT_A;
-      break;
-
-    case 0x1039u:
-      cat = (indic_category_t) OT_H;
-      break;
-
-    case 0x103Au:
-      cat = (indic_category_t) OT_As;
-      break;
-
-    case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
-    case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
-    case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
-    case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
-    case 0x1097u: case 0x1098u: case 0x1099u:
-      cat = (indic_category_t) OT_D;
-      break;
-
-    case 0x1040u:
-      cat = (indic_category_t) OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
-      break;
-
-    case 0x103Eu: case 0x1060u:
-      cat = (indic_category_t) OT_MH;
-      break;
-
-    case 0x103Cu:
-      cat = (indic_category_t) OT_MR;
-      break;
-
-    case 0x103Du: case 0x1082u:
-      cat = (indic_category_t) OT_MW;
-      break;
-
-    case 0x103Bu: case 0x105Eu: case 0x105Fu:
-      cat = (indic_category_t) OT_MY;
-      break;
-
-    case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
-    case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
-      cat = (indic_category_t) OT_PT;
-      break;
-
-    case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
-    case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
-    case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
-      cat = (indic_category_t) OT_SM;
-      break;
-
-    case 0x104Au: case 0x104Bu:
-      cat = (indic_category_t) OT_P;
-      break;
-
-    case 0xAA74u: case 0xAA75u: case 0xAA76u:
-      /* https://github.com/roozbehp/unicode-data/issues/3 */
-      cat = (indic_category_t) OT_C;
-      break;
-  }
-
-  if (cat == OT_M)
-  {
-    switch ((int) pos)
-    {
-      case POS_PRE_C:   cat = (indic_category_t) OT_VPre;
-                        pos = POS_PRE_M;                  break;
-      case POS_ABOVE_C: cat = (indic_category_t) OT_VAbv; break;
-      case POS_BELOW_C: cat = (indic_category_t) OT_VBlw; break;
-      case POS_POST_C:  cat = (indic_category_t) OT_VPst; break;
-    }
-  }
-
-  info.myanmar_category() = (myanmar_category_t) cat;
-  info.myanmar_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-myanmar-private.hh"
+#include "hb-ot-shape-complex-myanmar.hh"
 
 
 /*
@@ -36,7 +36,7 @@
 {
   /*
    * Basic features.
-   * These features are applied in order, one at a time, after initial_reordering.
+   * These features are applied in order, one at a time, after reordering.
    */
   HB_TAG('r','p','h','f'),
   HB_TAG('p','r','e','f'),
@@ -48,13 +48,20 @@
 {
   /*
    * Other features.
-   * These features are applied all at once, after final_reordering.
+   * These features are applied all at once, after clearing syllables.
    */
   HB_TAG('p','r','e','s'),
   HB_TAG('a','b','v','s'),
   HB_TAG('b','l','w','s'),
   HB_TAG('p','s','t','s'),
-  /* Positioning features, though we don't care about the types. */
+};
+static const hb_tag_t
+positioning_features[] =
+{
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   HB_TAG('d','i','s','t'),
   /* Pre-release version of Windows 8 Myanmar font had abvm,blwm
    * features.  The released Windows 8 version of the font (as well
@@ -73,13 +80,13 @@
                  hb_font_t *font,
                  hb_buffer_t *buffer);
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                    hb_font_t *font,
-                    hb_buffer_t *buffer);
+reorder (const hb_ot_shape_plan_t *plan,
+         hb_font_t *font,
+         hb_buffer_t *buffer);
 static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                  hb_font_t *font,
-                  hb_buffer_t *buffer);
+clear_syllables (const hb_ot_shape_plan_t *plan,
+                 hb_font_t *font,
+                 hb_buffer_t *buffer);
 
 static void
 collect_features_myanmar (hb_ot_shape_planner_t *plan)
@@ -89,27 +96,33 @@
   /* Do this before any lookups have been applied. */
   map->add_gsub_pause (setup_syllables);
 
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
   /* The Indic specs do not require ccmp, but we apply it here since if
    * there is a use of it, it's typically at the beginning. */
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
 
 
-  map->add_gsub_pause (initial_reordering);
+  map->add_gsub_pause (reorder);
+
   for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
   {
-    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
     map->add_gsub_pause (nullptr);
   }
-  map->add_gsub_pause (final_reordering);
+
+  map->add_gsub_pause (clear_syllables);
+
   for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
-    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (other_features[i], F_MANUAL_ZWJ);
+
+  for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
+    map->enable_feature (positioning_features[i]);
 }
 
 static void
 override_features_myanmar (hb_ot_shape_planner_t *plan)
 {
-  plan->map.add_feature (HB_TAG('l','i','g','a'), 0, F_GLOBAL);
+  plan->map.disable_feature (HB_TAG('l','i','g','a'));
 }
 
 
@@ -261,8 +274,8 @@
 }
 
 static void
-initial_reordering_syllable (const hb_ot_shape_plan_t *plan,
-                             hb_face_t *face,
+initial_reordering_syllable (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                             hb_face_t *face HB_UNUSED,
                              hb_buffer_t *buffer,
                              unsigned int start, unsigned int end)
 {
@@ -330,57 +343,34 @@
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
 static void
-initial_reordering (const hb_ot_shape_plan_t *plan,
-                    hb_font_t *font,
-                    hb_buffer_t *buffer)
+reorder (const hb_ot_shape_plan_t *plan,
+         hb_font_t *font,
+         hb_buffer_t *buffer)
 {
   insert_dotted_circles (plan, font, buffer);
 
   foreach_syllable (buffer, start, end)
     initial_reordering_syllable (plan, font->face, buffer, start, end);
-}
-
-static void
-final_reordering (const hb_ot_shape_plan_t *plan,
-                  hb_font_t *font HB_UNUSED,
-                  hb_buffer_t *buffer)
-{
-  hb_glyph_info_t *info = buffer->info;
-  unsigned int count = buffer->len;
-
-  /* Zero syllables now... */
-  for (unsigned int i = 0; i < count; i++)
-    info[i].syllable() = 0;
 
   HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
   HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
 }
 
-
-/* Uniscribe seems to have a shaper for 'mymr' that is like the
- * generic shaper, except that it zeros mark advances GDEF_LATE. */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_old =
+static void
+clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                 hb_font_t *font HB_UNUSED,
+                 hb_buffer_t *buffer)
 {
-  nullptr, /* collect_features */
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+    info[i].syllable() = 0;
+}
+
 
 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
 {
@@ -394,8 +384,30 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   setup_masks_myanmar,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
 };
+
+
+/* Ugly Zawgyi encoding.
+ * Disable all auto processing.
+ * https://github.com/harfbuzz/harfbuzz/issues/1162 */
+const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
+{
+  nullptr, /* collect_features */
+  nullptr, /* override_features */
+  nullptr, /* data_create */
+  nullptr, /* data_destroy */
+  nullptr, /* preprocess_text */
+  nullptr, /* postprocess_glyphs */
+  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
+  nullptr, /* decompose */
+  nullptr, /* compose */
+  nullptr, /* setup_masks */
+  HB_TAG_NONE, /* gpos_tag */
+  nullptr, /* reorder_marks */
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+  false, /* fallback_position */
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-myanmar.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,171 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_HH
+#define HB_OT_SHAPE_COMPLEX_MYANMAR_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex-indic.hh"
+
+
+/* buffer var allocations */
+#define myanmar_category() indic_category() /* myanmar_category_t */
+#define myanmar_position() indic_position() /* myanmar_position_t */
+
+
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum myanmar_category_t {
+  OT_As  = 18,  /* Asat */
+  OT_D0  = 20, /* Digit zero */
+  OT_DB  = OT_N, /* Dot below */
+  OT_GB  = OT_PLACEHOLDER,
+  OT_MH  = 21, /* Various consonant medial types */
+  OT_MR  = 22, /* Various consonant medial types */
+  OT_MW  = 23, /* Various consonant medial types */
+  OT_MY  = 24, /* Various consonant medial types */
+  OT_PT  = 25, /* Pwo and other tones */
+  OT_VAbv = 26,
+  OT_VBlw = 27,
+  OT_VPre = 28,
+  OT_VPst = 29,
+  OT_VS   = 30, /* Variation selectors */
+  OT_P    = 31, /* Punctuation */
+  OT_D    = 32, /* Digits except zero */
+};
+
+
+static inline void
+set_myanmar_properties (hb_glyph_info_t &info)
+{
+  hb_codepoint_t u = info.codepoint;
+  unsigned int type = hb_indic_get_categories (u);
+  unsigned int cat = type & 0x7Fu;
+  indic_position_t pos = (indic_position_t) (type >> 8);
+
+  /* Myanmar
+   * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
+   */
+  if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
+    cat = OT_VS;
+
+  switch (u)
+  {
+    case 0x104Eu:
+      cat = OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
+      break;
+
+    case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
+    case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
+    case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
+    case 0x25FEu:
+      cat = OT_GB;
+      break;
+
+    case 0x1004u: case 0x101Bu: case 0x105Au:
+      cat = OT_Ra;
+      break;
+
+    case 0x1032u: case 0x1036u:
+      cat = OT_A;
+      break;
+
+    case 0x1039u:
+      cat = OT_H;
+      break;
+
+    case 0x103Au:
+      cat = OT_As;
+      break;
+
+    case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
+    case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
+    case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
+    case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
+    case 0x1097u: case 0x1098u: case 0x1099u:
+      cat = OT_D;
+      break;
+
+    case 0x1040u:
+      cat = OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
+      break;
+
+    case 0x103Eu: case 0x1060u:
+      cat = OT_MH;
+      break;
+
+    case 0x103Cu:
+      cat = OT_MR;
+      break;
+
+    case 0x103Du: case 0x1082u:
+      cat = OT_MW;
+      break;
+
+    case 0x103Bu: case 0x105Eu: case 0x105Fu:
+      cat = OT_MY;
+      break;
+
+    case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
+    case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
+      cat = OT_PT;
+      break;
+
+    case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
+    case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
+    case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
+      cat = OT_SM;
+      break;
+
+    case 0x104Au: case 0x104Bu:
+      cat = OT_P;
+      break;
+
+    case 0xAA74u: case 0xAA75u: case 0xAA76u:
+      /* https://github.com/roozbehp/unicode-data/issues/3 */
+      cat = OT_C;
+      break;
+  }
+
+  if (cat == OT_M)
+  {
+    switch ((int) pos)
+    {
+      case POS_PRE_C:   cat = OT_VPre;
+                        pos = POS_PRE_M; break;
+      case POS_ABOVE_C: cat = OT_VAbv;   break;
+      case POS_BELOW_C: cat = OT_VBlw;   break;
+      case POS_POST_C:  cat = OT_VPst;   break;
+    }
+  }
+
+  info.myanmar_category() = cat;
+  info.myanmar_position() = pos;
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +0,0 @@
-/*
- * Copyright © 2010,2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-normalize-private.hh"
-
-
-
-/* buffer var allocations, used by complex shapers */
-#define complex_var_u8_0()      var2.u8[2]
-#define complex_var_u8_1()      var2.u8[3]
-
-
-#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
-
-enum hb_ot_shape_zero_width_marks_type_t {
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
-};
-
-
-/* Master OT shaper list */
-#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
-  HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
-  HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_old) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (tibetan) \
-  HB_COMPLEX_SHAPER_IMPLEMENT (use) \
-  /* ^--- Add new shapers here */
-
-
-struct hb_ot_complex_shaper_t
-{
-  /* collect_features()
-   * Called during shape_plan().
-   * Shapers should use plan->map to add their features and callbacks.
-   * May be nullptr.
-   */
-  void (*collect_features) (hb_ot_shape_planner_t *plan);
-
-  /* override_features()
-   * Called during shape_plan().
-   * Shapers should use plan->map to override features and add callbacks after
-   * common features are added.
-   * May be nullptr.
-   */
-  void (*override_features) (hb_ot_shape_planner_t *plan);
-
-
-  /* data_create()
-   * Called at the end of shape_plan().
-   * Whatever shapers return will be accessible through plan->data later.
-   * If nullptr is returned, means a plan failure.
-   */
-  void *(*data_create) (const hb_ot_shape_plan_t *plan);
-
-  /* data_destroy()
-   * Called when the shape_plan is being destroyed.
-   * plan->data is passed here for destruction.
-   * If nullptr is returned, means a plan failure.
-   * May be nullptr.
-   */
-  void (*data_destroy) (void *data);
-
-
-  /* preprocess_text()
-   * Called during shape().
-   * Shapers can use to modify text before shaping starts.
-   * May be nullptr.
-   */
-  void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
-                           hb_buffer_t              *buffer,
-                           hb_font_t                *font);
-
-  /* postprocess_glyphs()
-   * Called during shape().
-   * Shapers can use to modify glyphs after shaping ends.
-   * May be nullptr.
-   */
-  void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
-                              hb_buffer_t              *buffer,
-                              hb_font_t                *font);
-
-
-  hb_ot_shape_normalization_mode_t normalization_preference;
-
-  /* decompose()
-   * Called during shape()'s normalization.
-   * May be nullptr.
-   */
-  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
-                     hb_codepoint_t  ab,
-                     hb_codepoint_t *a,
-                     hb_codepoint_t *b);
-
-  /* compose()
-   * Called during shape()'s normalization.
-   * May be nullptr.
-   */
-  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
-                   hb_codepoint_t  a,
-                   hb_codepoint_t  b,
-                   hb_codepoint_t *ab);
-
-  /* setup_masks()
-   * Called during shape().
-   * Shapers should use map to get feature masks and set on buffer.
-   * Shapers may NOT modify characters.
-   * May be nullptr.
-   */
-  void (*setup_masks) (const hb_ot_shape_plan_t *plan,
-                       hb_buffer_t              *buffer,
-                       hb_font_t                *font);
-
-  /* disable_otl()
-   * Called during shape().
-   * If set and returns true, GDEF/GSUB/GPOS of the font are ignored
-   * and fallback operations used.
-   * May be nullptr.
-   */
-  bool (*disable_otl) (const hb_ot_shape_plan_t *plan);
-
-  /* reorder_marks()
-   * Called during shape().
-   * Shapers can use to modify ordering of combining marks.
-   * May be nullptr.
-   */
-  void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
-                         hb_buffer_t              *buffer,
-                         unsigned int              start,
-                         unsigned int              end);
-
-  hb_ot_shape_zero_width_marks_type_t zero_width_marks;
-
-  bool fallback_position;
-};
-
-#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
-HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
-#undef HB_COMPLEX_SHAPER_IMPLEMENT
-
-
-static inline const hb_ot_complex_shaper_t *
-hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
-{
-  switch ((hb_tag_t) planner->props.script)
-  {
-    default:
-      return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_ARABIC:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_MONGOLIAN:
-    case HB_SCRIPT_SYRIAC:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_NKO:
-    case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_PSALTER_PAHLAVI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_ADLAM:
-
-    /* Unicode-11.0 additions */
-    case HB_SCRIPT_HANIFI_ROHINGYA:
-    case HB_SCRIPT_SOGDIAN:
-
-      /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
-       * This is because we do fallback shaping for Arabic script (and not others).
-       * But note that Arabic shaping is applicable only to horizontal layout; for
-       * vertical text, just use the generic shaper instead. */
-      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
-           planner->props.script == HB_SCRIPT_ARABIC) &&
-          HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
-        return &_hb_ot_complex_shaper_arabic;
-      else
-        return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_THAI:
-    case HB_SCRIPT_LAO:
-
-      return &_hb_ot_complex_shaper_thai;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_HANGUL:
-
-      return &_hb_ot_complex_shaper_hangul;
-
-
-    /* Unicode-2.0 additions */
-    case HB_SCRIPT_TIBETAN:
-
-      return &_hb_ot_complex_shaper_tibetan;
-
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_HEBREW:
-
-      return &_hb_ot_complex_shaper_hebrew;
-
-
-    /* ^--- Add new shapers here */
-
-#if 0
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_NEW_TAI_LUE:
-#endif
-
-    /* Unicode-1.1 additions */
-    case HB_SCRIPT_BENGALI:
-    case HB_SCRIPT_DEVANAGARI:
-    case HB_SCRIPT_GUJARATI:
-    case HB_SCRIPT_GURMUKHI:
-    case HB_SCRIPT_KANNADA:
-    case HB_SCRIPT_MALAYALAM:
-    case HB_SCRIPT_ORIYA:
-    case HB_SCRIPT_TAMIL:
-    case HB_SCRIPT_TELUGU:
-
-    /* Unicode-3.0 additions */
-    case HB_SCRIPT_SINHALA:
-
-      /* If the designer designed the font for the 'DFLT' script,
-       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
-       * Otherwise, use the specific shaper.
-       * Note that for some simple scripts, there may not be *any*
-       * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
-        return &_hb_ot_complex_shaper_default;
-      else
-        return &_hb_ot_complex_shaper_indic;
-
-    case HB_SCRIPT_KHMER:
-      /* A number of Khmer fonts in the wild don't have a 'pref' feature,
-       * and as such won't shape properly via the Indic shaper;
-       * however, they typically have 'liga' / 'clig' features that implement
-       * the necessary "reordering" by means of ligature substitutions.
-       * So we send such pref-less fonts through the generic shaper instead. */
-      if (planner->map.found_script[0] &&
-          hb_ot_layout_language_find_feature (planner->face, HB_OT_TAG_GSUB,
-                                              planner->map.script_index[0],
-                                              planner->map.language_index[0],
-                                              HB_TAG ('p','r','e','f'),
-                                              nullptr))
-        return &_hb_ot_complex_shaper_khmer;
-      else
-        return &_hb_ot_complex_shaper_default;
-
-    case HB_SCRIPT_MYANMAR:
-      if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','2'))
-        return &_hb_ot_complex_shaper_myanmar;
-      else if (planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
-        return &_hb_ot_complex_shaper_myanmar_old;
-      else
-        return &_hb_ot_complex_shaper_default;
-
-
-    /* Unicode-2.0 additions */
-    //case HB_SCRIPT_TIBETAN:
-
-    /* Unicode-3.0 additions */
-    //case HB_SCRIPT_MONGOLIAN:
-    //case HB_SCRIPT_SINHALA:
-
-    /* Unicode-3.2 additions */
-    case HB_SCRIPT_BUHID:
-    case HB_SCRIPT_HANUNOO:
-    case HB_SCRIPT_TAGALOG:
-    case HB_SCRIPT_TAGBANWA:
-
-    /* Unicode-4.0 additions */
-    case HB_SCRIPT_LIMBU:
-    case HB_SCRIPT_TAI_LE:
-
-    /* Unicode-4.1 additions */
-    case HB_SCRIPT_BUGINESE:
-    case HB_SCRIPT_KHAROSHTHI:
-    case HB_SCRIPT_SYLOTI_NAGRI:
-    case HB_SCRIPT_TIFINAGH:
-
-    /* Unicode-5.0 additions */
-    case HB_SCRIPT_BALINESE:
-    //case HB_SCRIPT_NKO:
-    //case HB_SCRIPT_PHAGS_PA:
-
-    /* Unicode-5.1 additions */
-    case HB_SCRIPT_CHAM:
-    case HB_SCRIPT_KAYAH_LI:
-    case HB_SCRIPT_LEPCHA:
-    case HB_SCRIPT_REJANG:
-    case HB_SCRIPT_SAURASHTRA:
-    case HB_SCRIPT_SUNDANESE:
-
-    /* Unicode-5.2 additions */
-    case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
-    case HB_SCRIPT_JAVANESE:
-    case HB_SCRIPT_KAITHI:
-    case HB_SCRIPT_MEETEI_MAYEK:
-    case HB_SCRIPT_TAI_THAM:
-    case HB_SCRIPT_TAI_VIET:
-
-    /* Unicode-6.0 additions */
-    case HB_SCRIPT_BATAK:
-    case HB_SCRIPT_BRAHMI:
-    //case HB_SCRIPT_MANDAIC:
-
-    /* Unicode-6.1 additions */
-    case HB_SCRIPT_CHAKMA:
-    case HB_SCRIPT_SHARADA:
-    case HB_SCRIPT_TAKRI:
-
-    /* Unicode-7.0 additions */
-    case HB_SCRIPT_DUPLOYAN:
-    case HB_SCRIPT_GRANTHA:
-    case HB_SCRIPT_KHOJKI:
-    case HB_SCRIPT_KHUDAWADI:
-    case HB_SCRIPT_MAHAJANI:
-    //case HB_SCRIPT_MANICHAEAN:
-    case HB_SCRIPT_MODI:
-    case HB_SCRIPT_PAHAWH_HMONG:
-    //case HB_SCRIPT_PSALTER_PAHLAVI:
-    case HB_SCRIPT_SIDDHAM:
-    case HB_SCRIPT_TIRHUTA:
-
-    /* Unicode-8.0 additions */
-    case HB_SCRIPT_AHOM:
-    //case HB_SCRIPT_MULTANI:
-
-    /* Unicode-9.0 additions */
-    case HB_SCRIPT_BHAIKSUKI:
-    case HB_SCRIPT_MARCHEN:
-    case HB_SCRIPT_NEWA:
-
-    /* Unicode-10.0 additions */
-    case HB_SCRIPT_MASARAM_GONDI:
-    case HB_SCRIPT_SOYOMBO:
-    case HB_SCRIPT_ZANABAZAR_SQUARE:
-
-    /* Unicode-11.0 additions */
-    case HB_SCRIPT_DOGRA:
-    case HB_SCRIPT_GUNJALA_GONDI:
-    case HB_SCRIPT_MAKASAR:
-
-      /* If the designer designed the font for the 'DFLT' script,
-       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
-       * Otherwise, use the specific shaper.
-       * Note that for some simple scripts, there may not be *any*
-       * GSUB/GPOS needed, so there may be no scripts found! */
-      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
-          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
-        return &_hb_ot_complex_shaper_default;
-      else
-        return &_hb_ot_complex_shaper_use;
-  }
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-thai.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-thai.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,7 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-private.hh"
+#include "hb-ot-shape-complex.hh"
 
 
 /* Thai / Lao shaper */
@@ -324,9 +324,9 @@
     }
 
     /* Is SARA AM. Decompose and reorder. */
-    hb_codepoint_t decomposed[2] = {hb_codepoint_t (NIKHAHIT_FROM_SARA_AM (u)),
-                                    hb_codepoint_t (SARA_AA_FROM_SARA_AM (u))};
-    buffer->replace_glyphs (1, 2, decomposed);
+    hb_glyph_info_t &nikhahit = buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u));
+    _hb_glyph_info_set_continuation (&nikhahit);
+    buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u));
     if (unlikely (!buffer->successful))
       return;
 
@@ -376,7 +376,7 @@
   nullptr, /* decompose */
   nullptr, /* compose */
   nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
   false,/* fallback_position */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-tibetan.cc	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2010,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-static const hb_tag_t tibetan_features[] =
-{
-  HB_TAG('a','b','v','s'),
-  HB_TAG('b','l','w','s'),
-  HB_TAG('a','b','v','m'),
-  HB_TAG('b','l','w','m'),
-  HB_TAG_NONE
-};
-
-static void
-collect_features_tibetan (hb_ot_shape_planner_t *plan)
-{
-  for (const hb_tag_t *script_features = tibetan_features; script_features && *script_features; script_features++)
-    plan->map.add_global_bool_feature (*script_features);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_tibetan =
-{
-  collect_features_tibetan,
-  nullptr, /* override_features */
-  nullptr, /* data_create */
-  nullptr, /* data_destroy */
-  nullptr, /* preprocess_text */
-  nullptr, /* postprocess_glyphs */
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
-  nullptr, /* decompose */
-  nullptr, /* compose */
-  nullptr, /* setup_masks */
-  nullptr, /* disable_otl */
-  nullptr, /* reorder_marks */
-  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
-  true, /* fallback_position */
-};
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-machine.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-machine.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -31,232 +31,271 @@
 #ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 #define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 #line 38 "hb-ot-shape-complex-use-machine.hh"
 static const unsigned char _use_syllable_machine_trans_keys[] = {
-        12u, 12u, 1u, 15u, 1u, 1u, 12u, 12u, 0u, 43u, 21u, 21u, 8u, 39u, 8u, 39u,
-        1u, 15u, 1u, 1u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u,
-        8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
-        8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 13u, 21u, 4u, 4u, 13u, 13u, 8u, 39u,
-        8u, 39u, 8u, 39u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u, 8u, 39u,
-        8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u, 8u, 39u,
-        8u, 39u, 1u, 15u, 12u, 12u, 1u, 39u, 8u, 39u, 21u, 42u, 41u, 42u, 42u, 42u,
-        1u, 5u, 0
+        12u, 44u, 1u, 15u, 1u, 1u, 12u, 44u, 0u, 44u, 21u, 21u, 8u, 44u, 8u, 44u,
+        1u, 15u, 1u, 1u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u,
+        8u, 39u, 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
+        8u, 44u, 8u, 44u, 8u, 44u, 1u, 39u, 8u, 44u, 13u, 21u, 4u, 4u, 13u, 13u,
+        8u, 44u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u,
+        8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
+        8u, 44u, 8u, 44u, 1u, 39u, 1u, 15u, 12u, 44u, 1u, 44u, 8u, 44u, 21u, 42u,
+        41u, 42u, 42u, 42u, 1u, 5u, 0
 };
 
 static const char _use_syllable_machine_key_spans[] = {
-        1, 15, 1, 1, 44, 1, 32, 32,
-        15, 1, 32, 32, 32, 19, 19, 19,
-        32, 32, 32, 32, 32, 32, 32, 32,
-        32, 32, 32, 32, 9, 1, 1, 32,
-        32, 32, 32, 19, 19, 19, 32, 32,
-        32, 32, 32, 32, 32, 32, 32, 32,
-        32, 15, 1, 39, 32, 22, 2, 1,
-        5
+        33, 15, 1, 33, 45, 1, 37, 37,
+        15, 1, 37, 37, 32, 19, 19, 19,
+        32, 32, 32, 37, 37, 37, 37, 37,
+        37, 37, 37, 39, 37, 9, 1, 1,
+        37, 37, 37, 32, 19, 19, 19, 32,
+        32, 32, 37, 37, 37, 37, 37, 37,
+        37, 37, 39, 15, 33, 44, 37, 22,
+        2, 1, 5
 };
 
 static const short _use_syllable_machine_index_offsets[] = {
-        0, 2, 18, 20, 22, 67, 69, 102,
-        135, 151, 153, 186, 219, 252, 272, 292,
-        312, 345, 378, 411, 444, 477, 510, 543,
-        576, 609, 642, 675, 708, 718, 720, 722,
-        755, 788, 821, 854, 874, 894, 914, 947,
-        980, 1013, 1046, 1079, 1112, 1145, 1178, 1211,
-        1244, 1277, 1293, 1295, 1335, 1368, 1391, 1394,
-        1396
+        0, 34, 50, 52, 86, 132, 134, 172,
+        210, 226, 228, 266, 304, 337, 357, 377,
+        397, 430, 463, 496, 534, 572, 610, 648,
+        686, 724, 762, 800, 840, 878, 888, 890,
+        892, 930, 968, 1006, 1039, 1059, 1079, 1099,
+        1132, 1165, 1198, 1236, 1274, 1312, 1350, 1388,
+        1426, 1464, 1502, 1542, 1558, 1592, 1637, 1675,
+        1698, 1701, 1703
 };
 
 static const char _use_syllable_machine_indicies[] = {
+        1, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0,
         1, 0, 3, 2, 2, 2, 2, 2,
         2, 2, 2, 2, 2, 2, 2, 2,
-        4, 2, 3, 2, 6, 5, 7, 8,
+        4, 2, 3, 2, 6, 5, 5, 5,
+        5, 5, 5, 5, 5, 5, 5, 5,
+        5, 5, 5, 5, 5, 5, 5, 5,
+        5, 5, 5, 5, 5, 5, 5, 5,
+        5, 5, 5, 5, 6, 5, 7, 8,
         9, 7, 10, 8, 9, 9, 11, 9,
         9, 3, 12, 9, 9, 13, 7, 7,
         14, 15, 9, 9, 16, 17, 18, 19,
         20, 21, 22, 16, 23, 24, 25, 26,
         27, 28, 9, 29, 30, 31, 9, 9,
-        9, 32, 9, 34, 33, 36, 35, 35,
-        37, 1, 35, 35, 38, 35, 35, 35,
-        35, 35, 39, 40, 41, 42, 43, 44,
-        45, 46, 40, 47, 39, 48, 49, 50,
-        51, 35, 52, 53, 54, 35, 36, 35,
-        35, 37, 1, 35, 35, 38, 35, 35,
-        35, 35, 35, 55, 40, 41, 42, 43,
-        44, 45, 46, 40, 47, 48, 48, 49,
-        50, 51, 35, 52, 53, 54, 35, 37,
-        56, 56, 56, 56, 56, 56, 56, 56,
-        56, 56, 56, 56, 56, 57, 56, 37,
-        56, 36, 35, 35, 37, 1, 35, 35,
-        38, 35, 35, 35, 35, 35, 35, 40,
-        41, 42, 43, 44, 45, 46, 40, 47,
-        48, 48, 49, 50, 51, 35, 52, 53,
-        54, 35, 36, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        40, 41, 42, 43, 44, 35, 35, 35,
-        35, 35, 35, 49, 50, 51, 35, 52,
-        53, 54, 35, 36, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 41, 42, 43, 44, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        52, 53, 54, 35, 36, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 42, 43, 44, 35,
-        36, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 43, 44, 35, 36, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 44, 35,
-        36, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        42, 43, 44, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 52, 53, 54,
-        35, 36, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 42, 43, 44, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 53,
-        54, 35, 36, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 42, 43, 44, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 54, 35, 36, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 41, 42, 43, 44, 35, 35,
-        35, 35, 35, 35, 49, 50, 51, 35,
-        52, 53, 54, 35, 36, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 41, 42, 43, 44, 35,
-        35, 35, 35, 35, 35, 35, 50, 51,
-        35, 52, 53, 54, 35, 36, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 41, 42, 43, 44,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        51, 35, 52, 53, 54, 35, 36, 35,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 40, 41, 42, 43,
-        44, 35, 46, 40, 35, 35, 35, 49,
-        50, 51, 35, 52, 53, 54, 35, 36,
-        35, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 40, 41, 42,
-        43, 44, 35, 58, 40, 35, 35, 35,
-        49, 50, 51, 35, 52, 53, 54, 35,
-        36, 35, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 40, 41,
-        42, 43, 44, 35, 35, 40, 35, 35,
-        35, 49, 50, 51, 35, 52, 53, 54,
-        35, 36, 35, 35, 35, 35, 35, 35,
-        35, 35, 35, 35, 35, 35, 35, 40,
-        41, 42, 43, 44, 45, 46, 40, 35,
-        35, 35, 49, 50, 51, 35, 52, 53,
-        54, 35, 36, 35, 35, 37, 1, 35,
-        35, 38, 35, 35, 35, 35, 35, 35,
-        40, 41, 42, 43, 44, 45, 46, 40,
-        47, 35, 48, 49, 50, 51, 35, 52,
-        53, 54, 35, 36, 35, 35, 37, 1,
-        35, 35, 38, 35, 35, 35, 35, 35,
-        35, 40, 41, 42, 43, 44, 45, 46,
-        40, 47, 39, 48, 49, 50, 51, 35,
-        52, 53, 54, 35, 60, 59, 59, 59,
-        59, 59, 59, 59, 61, 59, 10, 62,
-        60, 59, 11, 63, 63, 3, 6, 63,
-        63, 64, 63, 63, 63, 63, 63, 65,
+        9, 32, 33, 9, 35, 34, 37, 36,
+        36, 38, 1, 36, 36, 39, 36, 36,
+        36, 36, 36, 40, 41, 42, 43, 44,
+        45, 46, 47, 41, 48, 40, 49, 50,
+        51, 52, 36, 53, 54, 55, 36, 36,
+        36, 36, 56, 36, 37, 36, 36, 38,
+        1, 36, 36, 39, 36, 36, 36, 36,
+        36, 57, 41, 42, 43, 44, 45, 46,
+        47, 41, 48, 49, 49, 50, 51, 52,
+        36, 53, 54, 55, 36, 36, 36, 36,
+        56, 36, 38, 58, 58, 58, 58, 58,
+        58, 58, 58, 58, 58, 58, 58, 58,
+        59, 58, 38, 58, 37, 36, 36, 38,
+        1, 36, 36, 39, 36, 36, 36, 36,
+        36, 36, 41, 42, 43, 44, 45, 46,
+        47, 41, 48, 49, 49, 50, 51, 52,
+        36, 53, 54, 55, 36, 36, 36, 36,
+        56, 36, 37, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        41, 42, 43, 44, 45, 36, 36, 36,
+        36, 36, 36, 50, 51, 52, 36, 53,
+        54, 55, 36, 36, 36, 36, 42, 36,
+        37, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 42,
+        43, 44, 45, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 53, 54, 55,
+        36, 37, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 43, 44, 45, 36, 37, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 44, 45,
+        36, 37, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 45, 36, 37, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 43, 44, 45,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 53, 54, 55, 36, 37, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 43, 44,
+        45, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 54, 55, 36, 37,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 43,
+        44, 45, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 55, 36,
+        37, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 42,
+        43, 44, 45, 36, 36, 36, 36, 36,
+        36, 50, 51, 52, 36, 53, 54, 55,
+        36, 36, 36, 36, 42, 36, 37, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 42, 43, 44,
+        45, 36, 36, 36, 36, 36, 36, 36,
+        51, 52, 36, 53, 54, 55, 36, 36,
+        36, 36, 42, 36, 37, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 42, 43, 44, 45, 36,
+        36, 36, 36, 36, 36, 36, 36, 52,
+        36, 53, 54, 55, 36, 36, 36, 36,
+        42, 36, 37, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        41, 42, 43, 44, 45, 36, 47, 41,
+        36, 36, 36, 50, 51, 52, 36, 53,
+        54, 55, 36, 36, 36, 36, 42, 36,
+        37, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 41, 42,
+        43, 44, 45, 36, 60, 41, 36, 36,
+        36, 50, 51, 52, 36, 53, 54, 55,
+        36, 36, 36, 36, 42, 36, 37, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 36, 36, 41, 42, 43, 44,
+        45, 36, 36, 41, 36, 36, 36, 50,
+        51, 52, 36, 53, 54, 55, 36, 36,
+        36, 36, 42, 36, 37, 36, 36, 36,
+        36, 36, 36, 36, 36, 36, 36, 36,
+        36, 36, 41, 42, 43, 44, 45, 46,
+        47, 41, 36, 36, 36, 50, 51, 52,
+        36, 53, 54, 55, 36, 36, 36, 36,
+        42, 36, 37, 36, 36, 38, 1, 36,
+        36, 39, 36, 36, 36, 36, 36, 36,
+        41, 42, 43, 44, 45, 46, 47, 41,
+        48, 36, 49, 50, 51, 52, 36, 53,
+        54, 55, 36, 36, 36, 36, 56, 36,
+        38, 58, 58, 58, 58, 58, 58, 37,
+        58, 58, 58, 58, 58, 58, 59, 58,
+        58, 58, 58, 58, 58, 58, 42, 43,
+        44, 45, 58, 58, 58, 58, 58, 58,
+        58, 58, 58, 58, 53, 54, 55, 58,
+        37, 36, 36, 38, 1, 36, 36, 39,
+        36, 36, 36, 36, 36, 36, 41, 42,
+        43, 44, 45, 46, 47, 41, 48, 40,
+        49, 50, 51, 52, 36, 53, 54, 55,
+        36, 36, 36, 36, 56, 36, 62, 61,
+        61, 61, 61, 61, 61, 61, 63, 61,
+        10, 64, 62, 61, 11, 65, 65, 3,
+        6, 65, 65, 66, 65, 65, 65, 65,
+        65, 67, 16, 17, 18, 19, 20, 21,
+        22, 16, 23, 25, 25, 26, 27, 28,
+        65, 29, 30, 31, 65, 65, 65, 65,
+        33, 65, 11, 65, 65, 3, 6, 65,
+        65, 66, 65, 65, 65, 65, 65, 65,
         16, 17, 18, 19, 20, 21, 22, 16,
-        23, 25, 25, 26, 27, 28, 63, 29,
-        30, 31, 63, 11, 63, 63, 3, 6,
-        63, 63, 64, 63, 63, 63, 63, 63,
-        63, 16, 17, 18, 19, 20, 21, 22,
-        16, 23, 25, 25, 26, 27, 28, 63,
-        29, 30, 31, 63, 11, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 16, 17, 18, 19, 20, 63,
-        63, 63, 63, 63, 63, 26, 27, 28,
-        63, 29, 30, 31, 63, 11, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 17, 18, 19, 20,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 29, 30, 31, 63, 11, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 18, 19,
-        20, 63, 11, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 19, 20, 63, 11, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        20, 63, 11, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 18, 19, 20, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 29,
-        30, 31, 63, 11, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 18, 19, 20, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 30, 31, 63, 11, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 18, 19, 20, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 31, 63, 11, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 17, 18, 19, 20,
-        63, 63, 63, 63, 63, 63, 26, 27,
-        28, 63, 29, 30, 31, 63, 11, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 17, 18, 19,
-        20, 63, 63, 63, 63, 63, 63, 63,
-        27, 28, 63, 29, 30, 31, 63, 11,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 17, 18,
-        19, 20, 63, 63, 63, 63, 63, 63,
-        63, 63, 28, 63, 29, 30, 31, 63,
-        11, 63, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 16, 17,
-        18, 19, 20, 63, 22, 16, 63, 63,
-        63, 26, 27, 28, 63, 29, 30, 31,
-        63, 11, 63, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 16,
-        17, 18, 19, 20, 63, 66, 16, 63,
-        63, 63, 26, 27, 28, 63, 29, 30,
-        31, 63, 11, 63, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        16, 17, 18, 19, 20, 63, 63, 16,
-        63, 63, 63, 26, 27, 28, 63, 29,
-        30, 31, 63, 11, 63, 63, 63, 63,
-        63, 63, 63, 63, 63, 63, 63, 63,
-        63, 16, 17, 18, 19, 20, 21, 22,
-        16, 63, 63, 63, 26, 27, 28, 63,
-        29, 30, 31, 63, 11, 63, 63, 3,
-        6, 63, 63, 64, 63, 63, 63, 63,
-        63, 63, 16, 17, 18, 19, 20, 21,
-        22, 16, 23, 63, 25, 26, 27, 28,
-        63, 29, 30, 31, 63, 3, 67, 67,
-        67, 67, 67, 67, 67, 67, 67, 67,
-        67, 67, 67, 4, 67, 6, 67, 8,
-        63, 63, 63, 8, 63, 63, 11, 63,
-        63, 3, 6, 63, 63, 64, 63, 63,
-        63, 63, 63, 63, 16, 17, 18, 19,
-        20, 21, 22, 16, 23, 24, 25, 26,
-        27, 28, 63, 29, 30, 31, 63, 11,
-        63, 63, 3, 6, 63, 63, 64, 63,
-        63, 63, 63, 63, 63, 16, 17, 18,
+        23, 25, 25, 26, 27, 28, 65, 29,
+        30, 31, 65, 65, 65, 65, 33, 65,
+        11, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 16, 17,
+        18, 19, 20, 65, 65, 65, 65, 65,
+        65, 26, 27, 28, 65, 29, 30, 31,
+        65, 65, 65, 65, 17, 65, 11, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 17, 18, 19,
+        20, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 29, 30, 31, 65, 11,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 18,
+        19, 20, 65, 11, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 19, 20, 65, 11,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 20, 65, 11, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 18, 19, 20, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        29, 30, 31, 65, 11, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 18, 19, 20, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 30, 31, 65, 11, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 18, 19, 20,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 31, 65, 11, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 17, 18, 19,
+        20, 65, 65, 65, 65, 65, 65, 26,
+        27, 28, 65, 29, 30, 31, 65, 65,
+        65, 65, 17, 65, 11, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 17, 18, 19, 20, 65,
+        65, 65, 65, 65, 65, 65, 27, 28,
+        65, 29, 30, 31, 65, 65, 65, 65,
+        17, 65, 11, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 17, 18, 19, 20, 65, 65, 65,
+        65, 65, 65, 65, 65, 28, 65, 29,
+        30, 31, 65, 65, 65, 65, 17, 65,
+        11, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 16, 17,
+        18, 19, 20, 65, 22, 16, 65, 65,
+        65, 26, 27, 28, 65, 29, 30, 31,
+        65, 65, 65, 65, 17, 65, 11, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 16, 17, 18, 19,
+        20, 65, 68, 16, 65, 65, 65, 26,
+        27, 28, 65, 29, 30, 31, 65, 65,
+        65, 65, 17, 65, 11, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 16, 17, 18, 19, 20, 65,
+        65, 16, 65, 65, 65, 26, 27, 28,
+        65, 29, 30, 31, 65, 65, 65, 65,
+        17, 65, 11, 65, 65, 65, 65, 65,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        16, 17, 18, 19, 20, 21, 22, 16,
+        65, 65, 65, 26, 27, 28, 65, 29,
+        30, 31, 65, 65, 65, 65, 17, 65,
+        11, 65, 65, 3, 6, 65, 65, 66,
+        65, 65, 65, 65, 65, 65, 16, 17,
+        18, 19, 20, 21, 22, 16, 23, 65,
+        25, 26, 27, 28, 65, 29, 30, 31,
+        65, 65, 65, 65, 33, 65, 3, 65,
+        65, 65, 65, 65, 65, 11, 65, 65,
+        65, 65, 65, 65, 4, 65, 65, 65,
+        65, 65, 65, 65, 17, 18, 19, 20,
+        65, 65, 65, 65, 65, 65, 65, 65,
+        65, 65, 29, 30, 31, 65, 3, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 4, 69, 6, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 69, 69,
+        69, 69, 69, 69, 69, 69, 6, 69,
+        8, 65, 65, 65, 8, 65, 65, 11,
+        65, 65, 3, 6, 65, 65, 66, 65,
+        65, 65, 65, 65, 65, 16, 17, 18,
         19, 20, 21, 22, 16, 23, 24, 25,
-        26, 27, 28, 63, 29, 30, 31, 63,
-        69, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 68, 68, 68, 68,
-        68, 68, 68, 68, 69, 70, 68, 69,
-        70, 68, 70, 68, 8, 67, 67, 67,
-        8, 67, 0
+        26, 27, 28, 65, 29, 30, 31, 65,
+        65, 65, 65, 33, 65, 11, 65, 65,
+        3, 6, 65, 65, 66, 65, 65, 65,
+        65, 65, 65, 16, 17, 18, 19, 20,
+        21, 22, 16, 23, 24, 25, 26, 27,
+        28, 65, 29, 30, 31, 65, 65, 65,
+        65, 33, 65, 71, 70, 70, 70, 70,
+        70, 70, 70, 70, 70, 70, 70, 70,
+        70, 70, 70, 70, 70, 70, 70, 71,
+        72, 70, 71, 72, 70, 72, 70, 8,
+        69, 69, 69, 8, 69, 0
 };
 
 static const char _use_syllable_machine_trans_targs[] = {
-        4, 8, 4, 31, 2, 4, 1, 5,
-        6, 4, 28, 4, 49, 50, 51, 53,
-        33, 34, 35, 36, 37, 44, 45, 47,
-        52, 48, 41, 42, 43, 38, 39, 40,
-        56, 4, 4, 4, 4, 7, 0, 27,
-        11, 12, 13, 14, 15, 22, 23, 25,
-        26, 19, 20, 21, 16, 17, 18, 10,
-        4, 9, 24, 4, 29, 30, 4, 4,
-        3, 32, 46, 4, 4, 54, 55
+        4, 8, 4, 32, 2, 4, 1, 5,
+        6, 4, 29, 4, 51, 52, 53, 55,
+        34, 35, 36, 37, 38, 45, 46, 48,
+        54, 49, 42, 43, 44, 39, 40, 41,
+        58, 50, 4, 4, 4, 4, 7, 0,
+        28, 11, 12, 13, 14, 15, 22, 23,
+        25, 26, 19, 20, 21, 16, 17, 18,
+        27, 10, 4, 9, 24, 4, 30, 31,
+        4, 4, 3, 33, 47, 4, 4, 56,
+        57
 };
 
 static const char _use_syllable_machine_trans_actions[] = {
@@ -264,11 +303,12 @@
         7, 8, 0, 9, 10, 10, 3, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         3, 3, 0, 0, 0, 0, 0, 0,
-        0, 11, 12, 13, 14, 7, 0, 7,
-        0, 0, 0, 0, 0, 0, 0, 0,
-        7, 0, 0, 0, 0, 0, 0, 7,
-        15, 0, 0, 16, 0, 0, 17, 18,
-        0, 3, 0, 19, 20, 0, 0
+        0, 3, 11, 12, 13, 14, 7, 0,
+        7, 0, 0, 0, 0, 0, 0, 0,
+        0, 7, 0, 0, 0, 0, 0, 0,
+        0, 7, 15, 0, 0, 16, 0, 0,
+        17, 18, 0, 3, 0, 19, 20, 0,
+        0
 };
 
 static const char _use_syllable_machine_to_state_actions[] = {
@@ -279,7 +319,7 @@
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0
+        0, 0, 0
 };
 
 static const char _use_syllable_machine_from_state_actions[] = {
@@ -290,18 +330,18 @@
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0,
-        0
+        0, 0, 0
 };
 
 static const short _use_syllable_machine_eof_trans[] = {
-        1, 3, 3, 6, 0, 34, 36, 36,
-        57, 57, 36, 36, 36, 36, 36, 36,
-        36, 36, 36, 36, 36, 36, 36, 36,
-        36, 36, 36, 36, 60, 63, 60, 64,
-        64, 64, 64, 64, 64, 64, 64, 64,
-        64, 64, 64, 64, 64, 64, 64, 64,
-        64, 68, 68, 64, 64, 69, 69, 69,
-        68
+        1, 3, 3, 6, 0, 35, 37, 37,
+        59, 59, 37, 37, 37, 37, 37, 37,
+        37, 37, 37, 37, 37, 37, 37, 37,
+        37, 37, 37, 59, 37, 62, 65, 62,
+        66, 66, 66, 66, 66, 66, 66, 66,
+        66, 66, 66, 66, 66, 66, 66, 66,
+        66, 66, 66, 70, 70, 66, 66, 71,
+        71, 71, 70
 };
 
 static const int use_syllable_machine_start = 4;
@@ -315,15 +355,14 @@
 
 
 
-#line 141 "hb-ot-shape-complex-use-machine.rl"
+#line 143 "hb-ot-shape-complex-use-machine.rl"
 
 
 #define found_syllable(syllable_type) \
   HB_STMT_START { \
-    if (0) fprintf (stderr, "syllable %d..%d %s\n", last, p+1, #syllable_type); \
-    for (unsigned int i = last; i < p+1; i++) \
+    if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+    for (unsigned int i = ts; i < te; i++) \
       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-    last = p+1; \
     syllable_serial++; \
     if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
   } HB_STMT_END
@@ -331,11 +370,11 @@
 static void
 find_syllables (hb_buffer_t *buffer)
 {
-  unsigned int p, pe, eof, ts HB_UNUSED, te, act;
+  unsigned int p, pe, eof, ts, te, act;
   int cs;
   hb_glyph_info_t *info = buffer->info;
 
-#line 339 "hb-ot-shape-complex-use-machine.hh"
+#line 378 "hb-ot-shape-complex-use-machine.hh"
         {
         cs = use_syllable_machine_start;
         ts = 0;
@@ -343,16 +382,15 @@
         act = 0;
         }
 
-#line 162 "hb-ot-shape-complex-use-machine.rl"
+#line 163 "hb-ot-shape-complex-use-machine.rl"
 
 
   p = 0;
   pe = eof = buffer->len;
 
-  unsigned int last = 0;
   unsigned int syllable_serial = 1;
 
-#line 356 "hb-ot-shape-complex-use-machine.hh"
+#line 394 "hb-ot-shape-complex-use-machine.hh"
         {
         int _slen;
         int _trans;
@@ -366,7 +404,7 @@
 #line 1 "NONE"
         {ts = p;}
         break;
-#line 370 "hb-ot-shape-complex-use-machine.hh"
+#line 408 "hb-ot-shape-complex-use-machine.hh"
         }
 
         _keys = _use_syllable_machine_trans_keys + (cs<<1);
@@ -389,59 +427,59 @@
         {te = p+1;}
         break;
         case 12:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 132 "hb-ot-shape-complex-use-machine.rl"
         {te = p+1;{ found_syllable (independent_cluster); }}
         break;
         case 14:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
         {te = p+1;{ found_syllable (standard_cluster); }}
         break;
         case 9:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
         {te = p+1;{ found_syllable (broken_cluster); }}
         break;
         case 8:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
         {te = p+1;{ found_syllable (non_cluster); }}
         break;
         case 11:
-#line 130 "hb-ot-shape-complex-use-machine.rl"
+#line 132 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (independent_cluster); }}
         break;
         case 15:
-#line 131 "hb-ot-shape-complex-use-machine.rl"
+#line 133 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (virama_terminated_cluster); }}
         break;
         case 13:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (standard_cluster); }}
         break;
         case 17:
-#line 133 "hb-ot-shape-complex-use-machine.rl"
+#line 135 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
         break;
         case 16:
-#line 134 "hb-ot-shape-complex-use-machine.rl"
+#line 136 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (numeral_cluster); }}
         break;
         case 20:
-#line 135 "hb-ot-shape-complex-use-machine.rl"
+#line 137 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (symbol_cluster); }}
         break;
         case 18:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (broken_cluster); }}
         break;
         case 19:
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
         {te = p;p--;{ found_syllable (non_cluster); }}
         break;
         case 1:
-#line 132 "hb-ot-shape-complex-use-machine.rl"
+#line 134 "hb-ot-shape-complex-use-machine.rl"
         {{p = ((te))-1;}{ found_syllable (standard_cluster); }}
         break;
         case 4:
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
         {{p = ((te))-1;}{ found_syllable (broken_cluster); }}
         break;
         case 2:
@@ -459,16 +497,16 @@
         case 3:
 #line 1 "NONE"
         {te = p+1;}
-#line 136 "hb-ot-shape-complex-use-machine.rl"
+#line 138 "hb-ot-shape-complex-use-machine.rl"
         {act = 7;}
         break;
         case 10:
 #line 1 "NONE"
         {te = p+1;}
-#line 137 "hb-ot-shape-complex-use-machine.rl"
+#line 139 "hb-ot-shape-complex-use-machine.rl"
         {act = 8;}
         break;
-#line 472 "hb-ot-shape-complex-use-machine.hh"
+#line 510 "hb-ot-shape-complex-use-machine.hh"
         }
 
 _again:
@@ -477,7 +515,7 @@
 #line 1 "NONE"
         {ts = 0;}
         break;
-#line 481 "hb-ot-shape-complex-use-machine.hh"
+#line 519 "hb-ot-shape-complex-use-machine.hh"
         }
 
         if ( ++p != pe )
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright © 2015  Mozilla Foundation.
- * Copyright © 2015  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-#include "hb-ot-shape-complex-private.hh"
-
-
-#define USE_TABLE_ELEMENT_TYPE uint8_t
-
-/* Cateories used in the Universal Shaping Engine spec:
- * https://docs.microsoft.com/en-us/typography/script-development/use
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum use_category_t {
-  USE_O         = 0,    /* OTHER */
-
-  USE_B         = 1,    /* BASE */
-  USE_IND       = 3,    /* BASE_IND */
-  USE_N         = 4,    /* BASE_NUM */
-  USE_GB        = 5,    /* BASE_OTHER */
-  USE_CGJ       = 6,    /* CGJ */
-//  USE_F               = 7,    /* CONS_FINAL */
-  USE_FM        = 8,    /* CONS_FINAL_MOD */
-//  USE_M               = 9,    /* CONS_MED */
-//  USE_CM      = 10,   /* CONS_MOD */
-  USE_SUB       = 11,   /* CONS_SUB */
-  USE_H         = 12,   /* HALANT */
-
-  USE_HN        = 13,   /* HALANT_NUM */
-  USE_ZWNJ      = 14,   /* Zero width non-joiner */
-  USE_ZWJ       = 15,   /* Zero width joiner */
-  USE_WJ        = 16,   /* Word joiner */
-  USE_Rsv       = 17,   /* Reserved characters */
-  USE_R         = 18,   /* REPHA */
-  USE_S         = 19,   /* SYM */
-//  USE_SM      = 20,   /* SYM_MOD */
-  USE_VS        = 21,   /* VARIATION_SELECTOR */
-//  USE_V       = 36,   /* VOWEL */
-//  USE_VM      = 40,   /* VOWEL_MOD */
-
-  USE_FAbv      = 24,   /* CONS_FINAL_ABOVE */
-  USE_FBlw      = 25,   /* CONS_FINAL_BELOW */
-  USE_FPst      = 26,   /* CONS_FINAL_POST */
-  USE_MAbv      = 27,   /* CONS_MED_ABOVE */
-  USE_MBlw      = 28,   /* CONS_MED_BELOW */
-  USE_MPst      = 29,   /* CONS_MED_POST */
-  USE_MPre      = 30,   /* CONS_MED_PRE */
-  USE_CMAbv     = 31,   /* CONS_MOD_ABOVE */
-  USE_CMBlw     = 32,   /* CONS_MOD_BELOW */
-  USE_VAbv      = 33,   /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
-  USE_VBlw      = 34,   /* VOWEL_BELOW / VOWEL_BELOW_POST */
-  USE_VPst      = 35,   /* VOWEL_POST   UIPC = Right */
-  USE_VPre      = 22,   /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
-  USE_VMAbv     = 37,   /* VOWEL_MOD_ABOVE */
-  USE_VMBlw     = 38,   /* VOWEL_MOD_BELOW */
-  USE_VMPst     = 39,   /* VOWEL_MOD_POST */
-  USE_VMPre     = 23,   /* VOWEL_MOD_PRE */
-  USE_SMAbv     = 41,   /* SYM_MOD_ABOVE */
-  USE_SMBlw     = 42,   /* SYM_MOD_BELOW */
-  USE_CS        = 43    /* CONS_WITH_STACKER */
-};
-
-HB_INTERNAL USE_TABLE_ELEMENT_TYPE
-hb_use_get_category (hb_codepoint_t u);
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-table.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use-table.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -15,8 +15,10 @@
  * UnicodeData.txt does not have a header.
  */
 
-#include "hb-ot-shape-complex-use-private.hh"
+#include "hb-ot-shape-complex-use.hh"
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
 #define B       USE_B   /* BASE */
 #define CGJ     USE_CGJ /* CGJ */
 #define CS      USE_CS  /* CONS_WITH_STACKER */
@@ -24,6 +26,7 @@
 #define GB      USE_GB  /* BASE_OTHER */
 #define H       USE_H   /* HALANT */
 #define HN      USE_HN  /* HALANT_NUM */
+#define HVM     USE_HVM /* HALANT_OR_VOWEL_MODIFIER */
 #define IND     USE_IND /* BASE_IND */
 #define N       USE_N   /* BASE_NUM */
 #define O       USE_O   /* OTHER */
@@ -54,6 +57,7 @@
 #define VMBlw   USE_VMBlw
 #define VMPst   USE_VMPst
 #define VMAbv   USE_VMAbv
+#pragma GCC diagnostic pop
 
 static const USE_TABLE_ELEMENT_TYPE use_table[] = {
 
@@ -101,7 +105,7 @@
   /* 0990 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 09A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 09B0 */     B,     O,     B,     O,     O,     O,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPre,
-  /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,   IND,     O,
+  /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPst,  VPst,     H,   IND,     O,
   /* 09D0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     B,     B,     O,     B,
   /* 09E0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O,    FM,     O,
@@ -134,7 +138,7 @@
   /* 0B10 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 0B30 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VAbv,
-  /* 0B40 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
+  /* 0B40 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPst,     O,     O,  VPst,  VPst,     H,     O,     O,
   /* 0B50 */     O,     O,     O,     O,     O,     O,  VAbv,  VAbv,     O,     O,     O,     O,     B,     B,     O,     B,
   /* 0B60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0B70 */     O,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -145,7 +149,7 @@
   /* 0B90 */     B,     O,     B,     B,     B,     B,     O,     O,     O,     B,     B,     O,     B,     O,     B,     B,
   /* 0BA0 */     O,     O,     O,     B,     B,     O,     O,     O,     B,     B,     B,     O,     O,     O,     B,     B,
   /* 0BB0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,  VPst,  VPst,
-  /* 0BC0 */  VAbv,  VPst,  VPst,     O,     O,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     O,     O,
+  /* 0BC0 */  VAbv,  VPst,  VPst,     O,     O,     O,  VPre,  VPre,  VPre,     O,  VPst,  VPst,  VPst,     H,     O,     O,
   /* 0BD0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 0BE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0BF0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -178,7 +182,7 @@
   /* 0D10 */     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,     B,  VPst,  VPst,
-  /* 0D40 */  VPst,  VPst,  VPst,  VBlw,  VBlw,     O,  VPre,  VPre,  VPre,     O,  VPre,  VPre,  VPre,     H,     R,     O,
+  /* 0D40 */  VPst,  VPst,  VPst,  VBlw,  VBlw,     O,  VPre,  VPre,  VPre,     O,  VPst,  VPst,  VPst,     H,     R,     O,
   /* 0D50 */     O,     O,     O,     O,   IND,   IND,   IND,  VPst,     O,     O,     O,     O,     O,     O,     O,     B,
   /* 0D60 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0D70 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,   IND,   IND,   IND,   IND,   IND,   IND,
@@ -190,11 +194,28 @@
   /* 0DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0DB0 */     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     O,     O,
   /* 0DC0 */     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     H,     O,     O,     O,     O,  VPst,
-  /* 0DD0 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,     O,  VBlw,     O,  VPst,  VPre,  VPre,  VPre,  VPre,  VPre,  VPre,  VPst,
+  /* 0DD0 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,     O,  VBlw,     O,  VPst,  VPre,  VPst,  VPre,  VPst,  VPst,  VPst,  VPst,
   /* 0DE0 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 0DF0 */     O,     O,  VPst,  VPst,     O,     O,     O,     O,
 
-#define use_offset_0x1000u 1360
+#define use_offset_0x0f18u 1360
+
+
+  /* Tibetan */
+                                                                      VBlw,  VBlw,     O,     O,     O,     O,     O,     O,
+  /* 0F20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F30 */     B,     B,     B,     B,     O,    FM,     O,    FM,     O, CMAbv,     O,     O,     O,     O,  VPst,  VPre,
+  /* 0F40 */     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 0F60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
+  /* 0F70 */     O,  VBlw,  VBlw,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw, VMAbv, VMPst,
+  /* 0F80 */  VBlw,  VAbv, VMAbv, VMAbv,  VBlw,   IND, VMAbv, VMAbv,     B,     B,     B,     B,     B,   SUB,   SUB,   SUB,
+  /* 0F90 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
+  /* 0FA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
+  /* 0FB0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,     O,     O,
+  /* 0FC0 */     O,     O,     O,     O,     O,     O,    FM,     O,
+
+#define use_offset_0x1000u 1536
 
 
   /* Myanmar */
@@ -210,7 +231,7 @@
   /* 1080 */     B,     B,  MBlw,  VPst,  VPre,  VAbv,  VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw,     B, VMPst,
   /* 1090 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B, VMPst, VMPst,  VPst,  VAbv,     O,     O,
 
-#define use_offset_0x1700u 1520
+#define use_offset_0x1700u 1696
 
 
   /* Tagalog */
@@ -238,12 +259,12 @@
   /* 1780 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1790 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 17A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPre,  VPre,
-  /* 17C0 */  VPre,  VPre,  VPre,  VPre,  VPre,  VPre, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
+  /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPst,  VPst,
+  /* 17C0 */  VPst,  VPre,  VPre,  VPre,  VPst,  VPst, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
   /* 17D0 */    FM,  VAbv,     H,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     B,  VAbv,     O,     O,
   /* 17E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1900u 1760
+#define use_offset_0x1900u 1936
 
 
   /* Limbu */
@@ -287,7 +308,7 @@
   /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1b00u 2176
+#define use_offset_0x1b00u 2352
 
 
   /* Balinese */
@@ -296,7 +317,7 @@
   /* 1B10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1B30 */     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VPre,
-  /* 1B40 */  VPre,  VPre,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
+  /* 1B40 */  VPst,  VPst,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
   /* 1B50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
   /* 1B60 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
   /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -319,11 +340,11 @@
 
   /* 1C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 1C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPre,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
+  /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPst,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
   /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre,    FM, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 1C40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,
 
-#define use_offset_0x1cd0u 2512
+#define use_offset_0x1cd0u 2688
 
 
   /* Vedic Extensions */
@@ -332,20 +353,20 @@
   /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,     O,     O,     O,     O, VMBlw,     O,     O,
   /* 1CF0 */     O,     O, VMPst, VMPst, VMAbv,    CS,    CS, VMPst, VMAbv, VMAbv,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x1df8u 2560
+#define use_offset_0x1df8u 2736
 
 
   /* Combining Diacritical Marks Supplement */
                                                                          O,     O,     O,    FM,     O,     O,     O,     O,
 
-#define use_offset_0x2008u 2568
+#define use_offset_0x2008u 2744
 
 
   /* General Punctuation */
                                                                          O,     O,     O,     O,  ZWNJ,   ZWJ,     O,     O,
   /* 2010 */    GB,    GB,    GB,    GB,    GB,     O,     O,     O,
 
-#define use_offset_0x2060u 2584
+#define use_offset_0x2060u 2760
 
   /* 2060 */    WJ,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
@@ -354,20 +375,20 @@
   /* 2070 */     O,     O,     O,     O,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 2080 */     O,     O,    FM,    FM,    FM,     O,     O,     O,
 
-#define use_offset_0x20f0u 2624
+#define use_offset_0x20f0u 2800
 
 
   /* Combining Diacritical Marks for Symbols */
 
   /* 20F0 */ VMAbv,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x25c8u 2632
+#define use_offset_0x25c8u 2808
 
 
   /* Geometric Shapes */
                                                                          O,     O,     O,     O,    GB,     O,     O,     O,
 
-#define use_offset_0xa800u 2640
+#define use_offset_0xa800u 2816
 
 
   /* Syloti Nagri */
@@ -454,7 +475,7 @@
   /* AAE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPre,  VBlw,  VAbv,  VPre,  VPst,
   /* AAF0 */     O,     O,     O,     O,     O, VMPst,     H,     O,
 
-#define use_offset_0xabc0u 3400
+#define use_offset_0xabc0u 3576
 
 
   /* Meetei Mayek */
@@ -464,14 +485,14 @@
   /* ABE0 */     B,     B,     B,  VPst,  VPst,  VAbv,  VPst,  VPst,  VBlw,  VPst,  VPst,     O, VMPst,  VBlw,     O,     O,
   /* ABF0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0xfe00u 3464
+#define use_offset_0xfe00u 3640
 
 
   /* Variation Selectors */
 
   /* FE00 */    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,    VS,
 
-#define use_offset_0x10a00u 3480
+#define use_offset_0x10a00u 3656
 
 
   /* Kharoshthi */
@@ -482,7 +503,7 @@
   /* 10A30 */     B,     B,     B,     B,     B,     B,     O,     O, CMAbv, CMBlw, CMBlw,     O,     O,     O,     O,     H,
   /* 10A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11000u 3560
+#define use_offset_0x11000u 3736
 
 
   /* Brahmi */
@@ -491,7 +512,7 @@
   /* 11010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11020 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11030 */     B,     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,
-  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,     H,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11040 */  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,   HVM,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11050 */     O,     O,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,     N,
   /* 11060 */     N,     N,     N,     N,     N,     N,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11070 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,    HN,
@@ -503,15 +524,15 @@
   /* 110A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 110B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VAbv,  VAbv,  VPst,  VPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11100u 3752
+#define use_offset_0x11100u 3928
 
 
   /* Chakma */
 
   /* 11100 */ VMAbv, VMAbv, VMAbv,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11110 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VAbv,  VAbv,
-  /* 11130 */  VAbv,  VBlw,  VBlw,     H,  VAbv,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
+  /* 11120 */     B,     B,     B,     B,     B,     B,     B,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VBlw,  VAbv,  VAbv,
+  /* 11130 */  VBlw,  VAbv,  VAbv,     H, CMBlw,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11140 */     O,     O,     O,     O,     B,  VPst,  VPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,
 
   /* Mahajani */
@@ -526,7 +547,7 @@
   /* 11190 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 111A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 111B0 */     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,
-  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,     O,    FM, CMBlw,  VAbv,  VBlw,     O,     O,     O,
+  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,    GB,  FBlw, CMBlw,  VAbv,  VBlw,     O,     O,     O,
   /* 111D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
   /* Sinhala Archaic Numbers */
@@ -541,7 +562,7 @@
   /* 11220 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPst,  VPst,  VBlw,
   /* 11230 */  VAbv,  VAbv,  VAbv,  VAbv, VMAbv,     H, CMAbv, CMAbv,     O,     O,     O,     O,     O,     O, VMAbv,     O,
 
-#define use_offset_0x11280u 4072
+#define use_offset_0x11280u 4248
 
 
   /* Multani */
@@ -560,16 +581,16 @@
 
   /* Grantha */
 
-  /* 11300 */ VMAbv, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
+  /* 11300 */ VMAbv, VMAbv, VMAbv, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
   /* 11310 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11320 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
   /* 11330 */     B,     O,     B,     B,     O,     B,     B,     B,     B,     B,     O, CMBlw, CMBlw,     B,  VPst,  VPst,
-  /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPre,  VPre,     H,     O,     O,
+  /* 11340 */  VAbv,  VPst,  VPst,  VPst,  VPst,     O,     O,  VPre,  VPre,     O,     O,  VPst,  VPst,   HVM,     O,     O,
   /* 11350 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     O,     O,     B,     B,
   /* 11360 */     B,     B,  VPst,  VPst,     O,     O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
   /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,     O,     O,     O,
 
-#define use_offset_0x11400u 4320
+#define use_offset_0x11400u 4496
 
 
   /* Newa */
@@ -588,11 +609,11 @@
   /* 11480 */     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11490 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 114A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-  /* 114B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VPre,  VAbv,  VPre,  VPre,  VPst,  VPre, VMAbv,
+  /* 114B0 */  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VPre,  VAbv,  VPst,  VPst,  VPst,  VPst, VMAbv,
   /* 114C0 */ VMAbv, VMPst,     H, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 114D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11580u 4544
+#define use_offset_0x11580u 4720
 
 
   /* Siddham */
@@ -600,7 +621,7 @@
   /* 11580 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11590 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 115A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
-  /* 115B0 */  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,  VPre,  VPre, VMAbv, VMAbv, VMPst,     H,
+  /* 115B0 */  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPst,  VPst,  VPst, VMAbv, VMAbv, VMPst,     H,
   /* 115C0 */ CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 115D0 */     O,     O,     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,  VBlw,  VBlw,     O,     O,
   /* 115E0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
@@ -635,7 +656,7 @@
   /* 11720 */  VPst,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VPre,  VAbv,  VBlw,  VAbv,  VAbv,  VAbv,     O,     O,     O,     O,
   /* 11730 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
 
-#define use_offset_0x11800u 4992
+#define use_offset_0x11800u 5168
 
 
   /* Dogra */
@@ -645,7 +666,7 @@
   /* 11820 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,
   /* 11830 */  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMPst,     H, CMBlw,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11a00u 5056
+#define use_offset_0x11a00u 5232
 
 
   /* Zanabazar Square */
@@ -664,7 +685,7 @@
   /* 11A80 */     B,     B,     B,     B,     O,     O,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
   /* 11A90 */  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw, VMAbv, VMPst, CMAbv,     H,     O,     O,     O,     B,     O,     O,
 
-#define use_offset_0x11c00u 5216
+#define use_offset_0x11c00u 5392
 
 
   /* Bhaiksuki */
@@ -673,7 +694,7 @@
   /* 11C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,  VPst,
   /* 11C30 */  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,     O,  VAbv,  VAbv,  VAbv,  VAbv, VMAbv, VMAbv, VMPst,     H,
-  /* 11C40 */     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
+  /* 11C40 */     B,     O,     O,     O,    GB,    GB,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11C50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11C60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
 
@@ -685,7 +706,7 @@
   /* 11CA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
   /* 11CB0 */  VBlw,  VPre,  VBlw,  VAbv,  VPst, VMAbv, VMAbv,     O,
 
-#define use_offset_0x11d00u 5400
+#define use_offset_0x11d00u 5576
 
 
   /* Masaram Gondi */
@@ -705,7 +726,7 @@
   /* 11D90 */  VAbv,  VAbv,     O,  VPst,  VPst, VMAbv, VMPst,     H,     O,     O,     O,     O,     O,     O,     O,     O,
   /* 11DA0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
 
-#define use_offset_0x11ee0u 5576
+#define use_offset_0x11ee0u 5752
 
 
   /* Makasar */
@@ -713,7 +734,7 @@
   /* 11EE0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
   /* 11EF0 */     B,     B,    GB,  VAbv,  VBlw,  VPre,  VPst,     O,
 
-}; /* Table items: 5600; occupancy: 73% */
+}; /* Table items: 5776; occupancy: 74% */
 
 USE_TABLE_ELEMENT_TYPE
 hb_use_get_category (hb_codepoint_t u)
@@ -725,6 +746,7 @@
       if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
       if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
+      if (hb_in_range<hb_codepoint_t> (u, 0x0F18u, 0x0FC7u)) return use_table[u - 0x0F18u + use_offset_0x0f18u];
       break;
 
     case 0x1u:
@@ -782,6 +804,7 @@
 #undef GB
 #undef H
 #undef HN
+#undef HVM
 #undef IND
 #undef N
 #undef O
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,8 +26,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-complex-use-private.hh"
-#include "hb-ot-shape-complex-arabic-private.hh"
+#include "hb-ot-shape-complex-use.hh"
+#include "hb-ot-shape-complex-arabic.hh"
+#include "hb-ot-shape-complex-vowel-constraints.hh"
 
 /* buffer var allocations */
 #define use_category() complex_var_u8_0()
@@ -79,14 +80,22 @@
 {
   /*
    * Other features.
-   * These features are applied all at once, after reordering.
+   * These features are applied all at once, after reordering and
+   * clearing syllables.
    */
   HB_TAG('a','b','v','s'),
   HB_TAG('b','l','w','s'),
   HB_TAG('h','a','l','n'),
   HB_TAG('p','r','e','s'),
   HB_TAG('p','s','t','s'),
-  /* Positioning features, though we don't care about the types. */
+};
+static const hb_tag_t
+positioning_features[] =
+{
+  /*
+   * Positioning features.
+   * We don't care about the types.
+   */
   HB_TAG('d','i','s','t'),
   HB_TAG('a','b','v','m'),
   HB_TAG('b','l','w','m'),
@@ -112,6 +121,10 @@
 reorder (const hb_ot_shape_plan_t *plan,
          hb_font_t *font,
          hb_buffer_t *buffer);
+static void
+clear_syllables (const hb_ot_shape_plan_t *plan,
+                 hb_font_t *font,
+                 hb_buffer_t *buffer);
 
 static void
 collect_features_use (hb_ot_shape_planner_t *plan)
@@ -122,39 +135,42 @@
   map->add_gsub_pause (setup_syllables);
 
   /* "Default glyph pre-processing group" */
-  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
-  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
-  map->add_global_bool_feature (HB_TAG('n','u','k','t'));
-  map->add_global_bool_feature (HB_TAG('a','k','h','n'));
+  map->enable_feature (HB_TAG('l','o','c','l'));
+  map->enable_feature (HB_TAG('c','c','m','p'));
+  map->enable_feature (HB_TAG('n','u','k','t'));
+  map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
 
   /* "Reordering group" */
   map->add_gsub_pause (clear_substitution_flags);
-  map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ);
+  map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
   map->add_gsub_pause (record_rphf);
   map->add_gsub_pause (clear_substitution_flags);
-  map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ);
+  map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
   map->add_gsub_pause (record_pref);
 
   /* "Orthographic unit shaping group" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
-    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
 
   map->add_gsub_pause (reorder);
+  map->add_gsub_pause (clear_syllables);
 
   /* "Topographical features" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
-    map->add_feature (arabic_features[i], 1, F_NONE);
+    map->add_feature (arabic_features[i]);
   map->add_gsub_pause (nullptr);
 
-  /* "Standard typographic presentation" and "Positional feature application" */
+  /* "Standard typographic presentation" */
   for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
-    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
+    map->enable_feature (other_features[i], F_MANUAL_ZWJ);
+
+  /* "Positional feature application" */
+  for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
+    map->enable_feature (positioning_features[i]);
 }
 
 struct use_shape_plan_t
 {
-  ASSERT_POD ();
-
   hb_mask_t rphf_mask;
 
   arabic_shape_plan_t *arabic_plan;
@@ -361,7 +377,7 @@
 }
 
 static void
-clear_substitution_flags (const hb_ot_shape_plan_t *plan,
+clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
                           hb_font_t *font HB_UNUSED,
                           hb_buffer_t *buffer)
 {
@@ -373,7 +389,7 @@
 
 static void
 record_rphf (const hb_ot_shape_plan_t *plan,
-             hb_font_t *font,
+             hb_font_t *font HB_UNUSED,
              hb_buffer_t *buffer)
 {
   const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
@@ -395,8 +411,8 @@
 }
 
 static void
-record_pref (const hb_ot_shape_plan_t *plan,
-             hb_font_t *font,
+record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
+             hb_font_t *font HB_UNUSED,
              hb_buffer_t *buffer)
 {
   hb_glyph_info_t *info = buffer->info;
@@ -416,7 +432,8 @@
 static inline bool
 is_halant (const hb_glyph_info_t &info)
 {
-  return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
+  return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
+         !_hb_glyph_info_ligated (&info);
 }
 
 static void
@@ -433,19 +450,38 @@
 
   hb_glyph_info_t *info = buffer->info;
 
-#define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB))
+#define POST_BASE_FLAGS64 (FLAG64 (USE_FM) | \
+                           FLAG64 (USE_FAbv) | \
+                           FLAG64 (USE_FBlw) | \
+                           FLAG64 (USE_FPst) | \
+                           FLAG64 (USE_MAbv) | \
+                           FLAG64 (USE_MBlw) | \
+                           FLAG64 (USE_MPst) | \
+                           FLAG64 (USE_MPre) | \
+                           FLAG64 (USE_VAbv) | \
+                           FLAG64 (USE_VBlw) | \
+                           FLAG64 (USE_VPst) | \
+                           FLAG64 (USE_VPre) | \
+                           FLAG64 (USE_VMAbv) | \
+                           FLAG64 (USE_VMBlw) | \
+                           FLAG64 (USE_VMPst) | \
+                           FLAG64 (USE_VMPre))
 
   /* Move things forward. */
   if (info[start].use_category() == USE_R && end - start > 1)
   {
-    /* Got a repha.  Reorder it to after first base, before first halant. */
+    /* Got a repha.  Reorder it towards the end, but before the first post-base
+     * glyph. */
     for (unsigned int i = start + 1; i < end; i++)
-      if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
+    {
+      bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
+                                is_halant (info[i]);
+      if (is_post_base_glyph || i == end - 1)
       {
-        /* If we hit a halant, move before it; otherwise it's a base: move to it's
-         * place, and shift things in between backward. */
+        /* If we hit a post-base glyph, move before it; otherwise move to the
+         * end. Shift things in between backward. */
 
-        if (is_halant (info[i]))
+        if (is_post_base_glyph)
           i--;
 
         buffer->merge_clusters (start, i + 1);
@@ -455,21 +491,19 @@
 
         break;
       }
+    }
   }
 
   /* Move things back. */
-  unsigned int j = end;
+  unsigned int j = start;
   for (unsigned int i = start; i < end; i++)
   {
     uint32_t flag = FLAG_UNSAFE (info[i].use_category());
-    if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
+    if (is_halant (info[i]))
     {
-      /* If we hit a halant, move after it; otherwise it's a base: move to it's
-       * place, and shift things in between backward. */
-      if (is_halant (info[i]))
-        j = i + 1;
-      else
-        j = i;
+      /* If we hit a halant, move after it; otherwise move to the beginning, and
+       * shift things in between forward. */
+      j = i + 1;
     }
     else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
              /* Only move the first component of a MultipleSubst. */
@@ -536,7 +570,6 @@
     else
       buffer->next_glyph ();
   }
-
   buffer->swap_buffers ();
 }
 
@@ -547,36 +580,30 @@
 {
   insert_dotted_circles (plan, font, buffer);
 
-  hb_glyph_info_t *info = buffer->info;
-
   foreach_syllable (buffer, start, end)
     reorder_syllable (buffer, start, end);
 
-  /* Zero syllables now... */
-  unsigned int count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
-    info[i].syllable() = 0;
-
   HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
 }
 
-static bool
-decompose_use (const hb_ot_shape_normalize_context_t *c,
-                hb_codepoint_t  ab,
-                hb_codepoint_t *a,
-                hb_codepoint_t *b)
+static void
+clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                 hb_font_t *font HB_UNUSED,
+                 hb_buffer_t *buffer)
 {
-  switch (ab)
-  {
-    /* Chakma:
-     * Special case where the Unicode decomp gives matras in the wrong order
-     * for cluster validation.
-     */
-    case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
-    case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
-  }
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+  for (unsigned int i = 0; i < count; i++)
+    info[i].syllable() = 0;
+}
+
 
-  return (bool) c->unicode->decompose (ab, a, b);
+static void
+preprocess_text_use (const hb_ot_shape_plan_t *plan,
+                     hb_buffer_t              *buffer,
+                     hb_font_t                *font)
+{
+  _hb_preprocess_text_vowel_constraints (plan, buffer, font);
 }
 
 static bool
@@ -599,13 +626,13 @@
   nullptr, /* override_features */
   data_create_use,
   data_destroy_use,
-  nullptr, /* preprocess_text */
+  preprocess_text_use,
   nullptr, /* postprocess_glyphs */
   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
-  decompose_use,
+  nullptr, /* decompose */
   compose_use,
   setup_masks_use,
-  nullptr, /* disable_otl */
+  HB_TAG_NONE, /* gpos_tag */
   nullptr, /* reorder_marks */
   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   false, /* fallback_position */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright © 2015  Mozilla Foundation.
+ * Copyright © 2015  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_USE_HH
+#define HB_OT_SHAPE_COMPLEX_USE_HH
+
+#include "hb.hh"
+
+
+#include "hb-ot-shape-complex.hh"
+
+
+#define USE_TABLE_ELEMENT_TYPE uint8_t
+
+/* Cateories used in the Universal Shaping Engine spec:
+ * https://docs.microsoft.com/en-us/typography/script-development/use
+ */
+/* Note: This enum is duplicated in the -machine.rl source file.
+ * Not sure how to avoid duplication. */
+enum use_category_t {
+  USE_O         = 0,    /* OTHER */
+
+  USE_B         = 1,    /* BASE */
+  USE_IND       = 3,    /* BASE_IND */
+  USE_N         = 4,    /* BASE_NUM */
+  USE_GB        = 5,    /* BASE_OTHER */
+  USE_CGJ       = 6,    /* CGJ */
+//  USE_F               = 7,    /* CONS_FINAL */
+  USE_FM        = 8,    /* CONS_FINAL_MOD */
+//  USE_M               = 9,    /* CONS_MED */
+//  USE_CM      = 10,   /* CONS_MOD */
+  USE_SUB       = 11,   /* CONS_SUB */
+  USE_H         = 12,   /* HALANT */
+
+  USE_HN        = 13,   /* HALANT_NUM */
+  USE_ZWNJ      = 14,   /* Zero width non-joiner */
+  USE_ZWJ       = 15,   /* Zero width joiner */
+  USE_WJ        = 16,   /* Word joiner */
+  USE_Rsv       = 17,   /* Reserved characters */
+  USE_R         = 18,   /* REPHA */
+  USE_S         = 19,   /* SYM */
+//  USE_SM      = 20,   /* SYM_MOD */
+  USE_VS        = 21,   /* VARIATION_SELECTOR */
+//  USE_V       = 36,   /* VOWEL */
+//  USE_VM      = 40,   /* VOWEL_MOD */
+
+  USE_FAbv      = 24,   /* CONS_FINAL_ABOVE */
+  USE_FBlw      = 25,   /* CONS_FINAL_BELOW */
+  USE_FPst      = 26,   /* CONS_FINAL_POST */
+  USE_MAbv      = 27,   /* CONS_MED_ABOVE */
+  USE_MBlw      = 28,   /* CONS_MED_BELOW */
+  USE_MPst      = 29,   /* CONS_MED_POST */
+  USE_MPre      = 30,   /* CONS_MED_PRE */
+  USE_CMAbv     = 31,   /* CONS_MOD_ABOVE */
+  USE_CMBlw     = 32,   /* CONS_MOD_BELOW */
+  USE_VAbv      = 33,   /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */
+  USE_VBlw      = 34,   /* VOWEL_BELOW / VOWEL_BELOW_POST */
+  USE_VPst      = 35,   /* VOWEL_POST   UIPC = Right */
+  USE_VPre      = 22,   /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
+  USE_VMAbv     = 37,   /* VOWEL_MOD_ABOVE */
+  USE_VMBlw     = 38,   /* VOWEL_MOD_BELOW */
+  USE_VMPst     = 39,   /* VOWEL_MOD_POST */
+  USE_VMPre     = 23,   /* VOWEL_MOD_PRE */
+  USE_SMAbv     = 41,   /* SYM_MOD_ABOVE */
+  USE_SMBlw     = 42,   /* SYM_MOD_BELOW */
+  USE_CS        = 43,   /* CONS_WITH_STACKER */
+
+  /* https://github.com/harfbuzz/harfbuzz/issues/1102 */
+  USE_HVM       = 44,   /* HALANT_OR_VOWEL_MODIFIER */
+};
+
+HB_INTERNAL USE_TABLE_ELEMENT_TYPE
+hb_use_get_category (hb_codepoint_t u);
+
+#endif /* HB_OT_SHAPE_COMPLEX_USE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-vowel-constraints.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,437 @@
+/* == Start of generated functions == */
+/*
+ * The following functions are generated by running:
+ *
+ *   ./gen-vowel-constraints.py use Scripts.txt
+ *
+ * on files with these headers:
+ *
+ * # Copied from https://docs.microsoft.com/en-us/typography/script-development/use
+ * # On October 23, 2018; with documentd dated 02/07/2018.
+ *
+ * # Scripts-11.0.0.txt
+ * # Date: 2018-02-21, 05:34:31 GMT
+ */
+
+#include "hb-ot-shape-complex-vowel-constraints.hh"
+
+static void
+_output_dotted_circle (hb_buffer_t *buffer)
+{
+  hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);
+  _hb_glyph_info_reset_continuation (&dottedcircle);
+}
+
+static void
+_output_with_dotted_circle (hb_buffer_t *buffer)
+{
+  _output_dotted_circle (buffer);
+  buffer->next_glyph ();
+}
+
+void
+_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                       hb_buffer_t              *buffer,
+                                       hb_font_t                *font HB_UNUSED)
+{
+  /* UGLY UGLY UGLY business of adding dotted-circle in the middle of
+   * vowel-sequences that look like another vowel.  Data for each script
+   * collected from the USE script development spec.
+   *
+   * https://github.com/harfbuzz/harfbuzz/issues/1019
+   */
+  bool processed = false;
+  buffer->clear_output ();
+  unsigned int count = buffer->len;
+  switch ((unsigned) buffer->props.script)
+  {
+    case HB_SCRIPT_DEVANAGARI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0905u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u:
+              case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu:
+              case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0906u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u:
+              case 0x0948u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0909u:
+            matched = 0x0941u == buffer->cur (1).codepoint;
+            break;
+          case 0x090Fu:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0945u: case 0x0946u: case 0x0947u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0930u:
+            if (0x094Du == buffer->cur (1).codepoint &&
+                buffer->idx + 2 < count &&
+                0x0907u == buffer->cur (2).codepoint)
+            {
+              buffer->next_glyph ();
+              buffer->next_glyph ();
+              _output_dotted_circle (buffer);
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_BENGALI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0985u:
+            matched = 0x09BEu == buffer->cur (1).codepoint;
+            break;
+          case 0x098Bu:
+            matched = 0x09C3u == buffer->cur (1).codepoint;
+            break;
+          case 0x098Cu:
+            matched = 0x09E2u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_GURMUKHI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0A05u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0A72u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0A3Fu: case 0x0A40u: case 0x0A47u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0A73u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0A41u: case 0x0A42u: case 0x0A4Bu:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_GUJARATI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0A85u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u:
+              case 0x0AC9u: case 0x0ACBu: case 0x0ACCu:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0AC5u:
+            matched = 0x0ABEu == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_ORIYA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0B05u:
+            matched = 0x0B3Eu == buffer->cur (1).codepoint;
+            break;
+          case 0x0B0Fu: case 0x0B13u:
+            matched = 0x0B57u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TELUGU:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0C12u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0C4Cu: case 0x0C55u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0C3Fu: case 0x0C46u: case 0x0C4Au:
+            matched = 0x0C55u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_KANNADA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0C89u: case 0x0C8Bu:
+            matched = 0x0CBEu == buffer->cur (1).codepoint;
+            break;
+          case 0x0C92u:
+            matched = 0x0CCCu == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_MALAYALAM:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0D07u: case 0x0D09u:
+            matched = 0x0D57u == buffer->cur (1).codepoint;
+            break;
+          case 0x0D0Eu:
+            matched = 0x0D46u == buffer->cur (1).codepoint;
+            break;
+          case 0x0D12u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0D3Eu: case 0x0D57u:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_SINHALA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x0D85u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0DCFu: case 0x0DD0u: case 0x0DD1u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u:
+            matched = 0x0DDFu == buffer->cur (1).codepoint;
+            break;
+          case 0x0D8Du:
+            matched = 0x0DD8u == buffer->cur (1).codepoint;
+            break;
+          case 0x0D91u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu:
+              case 0x0DDDu:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_BRAHMI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x11005u:
+            matched = 0x11038u == buffer->cur (1).codepoint;
+            break;
+          case 0x1100Bu:
+            matched = 0x1103Eu == buffer->cur (1).codepoint;
+            break;
+          case 0x1100Fu:
+            matched = 0x11042u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_KHUDAWADI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x112B0u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u:
+              case 0x112E8u:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TIRHUTA:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x11481u:
+            matched = 0x114B0u == buffer->cur (1).codepoint;
+            break;
+          case 0x1148Bu: case 0x1148Du:
+            matched = 0x114BAu == buffer->cur (1).codepoint;
+            break;
+          case 0x114AAu:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x114B5u: case 0x114B6u:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_MODI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x11600u: case 0x11601u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x11639u: case 0x1163Au:
+                matched = true;
+                break;
+            }
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    case HB_SCRIPT_TAKRI:
+      for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+      {
+        bool matched = false;
+        switch (buffer->cur ().codepoint)
+        {
+          case 0x11680u:
+            switch (buffer->cur (1).codepoint)
+            {
+              case 0x116ADu: case 0x116B4u: case 0x116B5u:
+                matched = true;
+                break;
+            }
+            break;
+          case 0x11686u:
+            matched = 0x116B2u == buffer->cur (1).codepoint;
+            break;
+        }
+        buffer->next_glyph ();
+        if (matched) _output_with_dotted_circle (buffer);
+      }
+      processed = true;
+      break;
+
+    default:
+      break;
+  }
+  if (processed)
+  {
+    if (buffer->idx < count)
+      buffer->next_glyph ();
+    buffer->swap_buffers ();
+  }
+}
+
+/* == End of generated functions == */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-vowel-constraints.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
+#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape-complex.hh"
+
+HB_INTERNAL void
+_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,
+                                       hb_buffer_t              *buffer,
+                                       hb_font_t                *font);
+
+#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2010,2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_COMPLEX_HH
+#define HB_OT_SHAPE_COMPLEX_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-shape-normalize.hh"
+
+
+/* buffer var allocations, used by complex shapers */
+#define complex_var_u8_0()      var2.u8[2]
+#define complex_var_u8_1()      var2.u8[3]
+
+
+#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
+
+enum hb_ot_shape_zero_width_marks_type_t {
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
+  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
+};
+
+
+/* Master OT shaper list */
+#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
+  HB_COMPLEX_SHAPER_IMPLEMENT (default) /* should be first */ \
+  HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
+  HB_COMPLEX_SHAPER_IMPLEMENT (use) \
+  /* ^--- Add new shapers here */
+
+
+struct hb_ot_complex_shaper_t
+{
+  /* collect_features()
+   * Called during shape_plan().
+   * Shapers should use plan->map to add their features and callbacks.
+   * May be NULL.
+   */
+  void (*collect_features) (hb_ot_shape_planner_t *plan);
+
+  /* override_features()
+   * Called during shape_plan().
+   * Shapers should use plan->map to override features and add callbacks after
+   * common features are added.
+   * May be NULL.
+   */
+  void (*override_features) (hb_ot_shape_planner_t *plan);
+
+
+  /* data_create()
+   * Called at the end of shape_plan().
+   * Whatever shapers return will be accessible through plan->data later.
+   * If nullptr is returned, means a plan failure.
+   */
+  void *(*data_create) (const hb_ot_shape_plan_t *plan);
+
+  /* data_destroy()
+   * Called when the shape_plan is being destroyed.
+   * plan->data is passed here for destruction.
+   * If nullptr is returned, means a plan failure.
+   * May be NULL.
+   */
+  void (*data_destroy) (void *data);
+
+
+  /* preprocess_text()
+   * Called during shape().
+   * Shapers can use to modify text before shaping starts.
+   * May be NULL.
+   */
+  void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
+                           hb_buffer_t              *buffer,
+                           hb_font_t                *font);
+
+  /* postprocess_glyphs()
+   * Called during shape().
+   * Shapers can use to modify glyphs after shaping ends.
+   * May be NULL.
+   */
+  void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
+                              hb_buffer_t              *buffer,
+                              hb_font_t                *font);
+
+
+  hb_ot_shape_normalization_mode_t normalization_preference;
+
+  /* decompose()
+   * Called during shape()'s normalization.
+   * May be NULL.
+   */
+  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+                     hb_codepoint_t  ab,
+                     hb_codepoint_t *a,
+                     hb_codepoint_t *b);
+
+  /* compose()
+   * Called during shape()'s normalization.
+   * May be NULL.
+   */
+  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
+                   hb_codepoint_t  a,
+                   hb_codepoint_t  b,
+                   hb_codepoint_t *ab);
+
+  /* setup_masks()
+   * Called during shape().
+   * Shapers should use map to get feature masks and set on buffer.
+   * Shapers may NOT modify characters.
+   * May be NULL.
+   */
+  void (*setup_masks) (const hb_ot_shape_plan_t *plan,
+                       hb_buffer_t              *buffer,
+                       hb_font_t                *font);
+
+  /* gpos_tag()
+   * If not HB_TAG_NONE, then must match found GPOS script tag for
+   * GPOS to be applied.  Otherwise, fallback positioning will be used.
+   */
+  hb_tag_t gpos_tag;
+
+  /* reorder_marks()
+   * Called during shape().
+   * Shapers can use to modify ordering of combining marks.
+   * May be NULL.
+   */
+  void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
+                         hb_buffer_t              *buffer,
+                         unsigned int              start,
+                         unsigned int              end);
+
+  hb_ot_shape_zero_width_marks_type_t zero_width_marks;
+
+  bool fallback_position;
+};
+
+#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
+HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_COMPLEX_SHAPER_IMPLEMENT
+
+
+static inline const hb_ot_complex_shaper_t *
+hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
+{
+  switch ((hb_tag_t) planner->props.script)
+  {
+    default:
+      return &_hb_ot_complex_shaper_default;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_ARABIC:
+
+    /* Unicode-3.0 additions */
+    case HB_SCRIPT_MONGOLIAN:
+    case HB_SCRIPT_SYRIAC:
+
+    /* Unicode-5.0 additions */
+    case HB_SCRIPT_NKO:
+    case HB_SCRIPT_PHAGS_PA:
+
+    /* Unicode-6.0 additions */
+    case HB_SCRIPT_MANDAIC:
+
+    /* Unicode-7.0 additions */
+    case HB_SCRIPT_MANICHAEAN:
+    case HB_SCRIPT_PSALTER_PAHLAVI:
+
+    /* Unicode-9.0 additions */
+    case HB_SCRIPT_ADLAM:
+
+    /* Unicode-11.0 additions */
+    case HB_SCRIPT_HANIFI_ROHINGYA:
+    case HB_SCRIPT_SOGDIAN:
+
+      /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
+       * This is because we do fallback shaping for Arabic script (and not others).
+       * But note that Arabic shaping is applicable only to horizontal layout; for
+       * vertical text, just use the generic shaper instead. */
+      if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
+           planner->props.script == HB_SCRIPT_ARABIC) &&
+          HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
+        return &_hb_ot_complex_shaper_arabic;
+      else
+        return &_hb_ot_complex_shaper_default;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_THAI:
+    case HB_SCRIPT_LAO:
+
+      return &_hb_ot_complex_shaper_thai;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_HANGUL:
+
+      return &_hb_ot_complex_shaper_hangul;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_HEBREW:
+
+      return &_hb_ot_complex_shaper_hebrew;
+
+
+    /* Unicode-1.1 additions */
+    case HB_SCRIPT_BENGALI:
+    case HB_SCRIPT_DEVANAGARI:
+    case HB_SCRIPT_GUJARATI:
+    case HB_SCRIPT_GURMUKHI:
+    case HB_SCRIPT_KANNADA:
+    case HB_SCRIPT_MALAYALAM:
+    case HB_SCRIPT_ORIYA:
+    case HB_SCRIPT_TAMIL:
+    case HB_SCRIPT_TELUGU:
+
+    /* Unicode-3.0 additions */
+    case HB_SCRIPT_SINHALA:
+
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       *
+       * If it's indy3 tag, send to USE. */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+        return &_hb_ot_complex_shaper_default;
+      else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
+        return &_hb_ot_complex_shaper_use;
+      else
+        return &_hb_ot_complex_shaper_indic;
+
+    case HB_SCRIPT_KHMER:
+        return &_hb_ot_complex_shaper_khmer;
+
+    case HB_SCRIPT_MYANMAR:
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       *
+       * If designer designed for 'mymr' tag, also send to default
+       * shaper.  That's tag used from before Myanmar shaping spec
+       * was developed.  The shaping spec uses 'mym2' tag. */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
+          planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
+        return &_hb_ot_complex_shaper_default;
+      else
+        return &_hb_ot_complex_shaper_myanmar;
+
+
+    /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
+    case HB_SCRIPT_MYANMAR_ZAWGYI:
+
+      return &_hb_ot_complex_shaper_myanmar_zawgyi;
+
+
+    /* Unicode-2.0 additions */
+    case HB_SCRIPT_TIBETAN:
+
+    /* Unicode-3.0 additions */
+    //case HB_SCRIPT_MONGOLIAN:
+    //case HB_SCRIPT_SINHALA:
+
+    /* Unicode-3.2 additions */
+    case HB_SCRIPT_BUHID:
+    case HB_SCRIPT_HANUNOO:
+    case HB_SCRIPT_TAGALOG:
+    case HB_SCRIPT_TAGBANWA:
+
+    /* Unicode-4.0 additions */
+    case HB_SCRIPT_LIMBU:
+    case HB_SCRIPT_TAI_LE:
+
+    /* Unicode-4.1 additions */
+    case HB_SCRIPT_BUGINESE:
+    case HB_SCRIPT_KHAROSHTHI:
+    case HB_SCRIPT_SYLOTI_NAGRI:
+    case HB_SCRIPT_TIFINAGH:
+
+    /* Unicode-5.0 additions */
+    case HB_SCRIPT_BALINESE:
+    //case HB_SCRIPT_NKO:
+    //case HB_SCRIPT_PHAGS_PA:
+
+    /* Unicode-5.1 additions */
+    case HB_SCRIPT_CHAM:
+    case HB_SCRIPT_KAYAH_LI:
+    case HB_SCRIPT_LEPCHA:
+    case HB_SCRIPT_REJANG:
+    case HB_SCRIPT_SAURASHTRA:
+    case HB_SCRIPT_SUNDANESE:
+
+    /* Unicode-5.2 additions */
+    case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
+    case HB_SCRIPT_JAVANESE:
+    case HB_SCRIPT_KAITHI:
+    case HB_SCRIPT_MEETEI_MAYEK:
+    case HB_SCRIPT_TAI_THAM:
+    case HB_SCRIPT_TAI_VIET:
+
+    /* Unicode-6.0 additions */
+    case HB_SCRIPT_BATAK:
+    case HB_SCRIPT_BRAHMI:
+    //case HB_SCRIPT_MANDAIC:
+
+    /* Unicode-6.1 additions */
+    case HB_SCRIPT_CHAKMA:
+    case HB_SCRIPT_SHARADA:
+    case HB_SCRIPT_TAKRI:
+
+    /* Unicode-7.0 additions */
+    case HB_SCRIPT_DUPLOYAN:
+    case HB_SCRIPT_GRANTHA:
+    case HB_SCRIPT_KHOJKI:
+    case HB_SCRIPT_KHUDAWADI:
+    case HB_SCRIPT_MAHAJANI:
+    //case HB_SCRIPT_MANICHAEAN:
+    case HB_SCRIPT_MODI:
+    case HB_SCRIPT_PAHAWH_HMONG:
+    //case HB_SCRIPT_PSALTER_PAHLAVI:
+    case HB_SCRIPT_SIDDHAM:
+    case HB_SCRIPT_TIRHUTA:
+
+    /* Unicode-8.0 additions */
+    case HB_SCRIPT_AHOM:
+
+    /* Unicode-9.0 additions */
+    //case HB_SCRIPT_ADLAM:
+    case HB_SCRIPT_BHAIKSUKI:
+    case HB_SCRIPT_MARCHEN:
+    case HB_SCRIPT_NEWA:
+
+    /* Unicode-10.0 additions */
+    case HB_SCRIPT_MASARAM_GONDI:
+    case HB_SCRIPT_SOYOMBO:
+    case HB_SCRIPT_ZANABAZAR_SQUARE:
+
+    /* Unicode-11.0 additions */
+    case HB_SCRIPT_DOGRA:
+    case HB_SCRIPT_GUNJALA_GONDI:
+    //case HB_SCRIPT_HANIFI_ROHINGYA:
+    case HB_SCRIPT_MAKASAR:
+    //case HB_SCRIPT_SOGDIAN:
+
+      /* If the designer designed the font for the 'DFLT' script,
+       * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+       * Otherwise, use the specific shaper.
+       * Note that for some simple scripts, there may not be *any*
+       * GSUB/GPOS needed, so there may be no scripts found! */
+      if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+          planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+        return &_hb_ot_complex_shaper_default;
+      else
+        return &_hb_ot_complex_shaper_use;
+  }
+}
+
+
+#endif /* HB_OT_SHAPE_COMPLEX_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_FALLBACK_PRIVATE_HH
-#define HB_OT_SHAPE_FALLBACK_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-shape-private.hh"
-
-
-HB_INTERNAL void _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
-                                                 hb_font_t *font,
-                                                 hb_buffer_t  *buffer);
-
-HB_INTERNAL void _hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan,
-                                                                    hb_font_t *font,
-                                                                    hb_buffer_t  *buffer);
-
-
-HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
-                                             hb_font_t *font,
-                                             hb_buffer_t  *buffer);
-
-HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
-                                               hb_font_t *font,
-                                               hb_buffer_t  *buffer);
-
-
-#endif /* HB_OT_SHAPE_FALLBACK_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,8 +24,8 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-fallback-private.hh"
-#include "hb-ot-layout-gsubgpos-private.hh"
+#include "hb-ot-shape-fallback.hh"
+#include "hb-kern.hh"
 
 static unsigned int
 recategorize_combining_class (hb_codepoint_t u,
@@ -162,9 +162,9 @@
 }
 
 void
-_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
-                                                   hb_font_t *font HB_UNUSED,
-                                                   hb_buffer_t  *buffer)
+_hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
+                                                        hb_font_t *font HB_UNUSED,
+                                                        hb_buffer_t  *buffer)
 {
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
@@ -180,19 +180,25 @@
 static void
 zero_mark_advances (hb_buffer_t *buffer,
                     unsigned int start,
-                    unsigned int end)
+                    unsigned int end,
+                    bool adjust_offsets_when_zeroing)
 {
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = start; i < end; i++)
     if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
     {
+      if (adjust_offsets_when_zeroing)
+      {
+        buffer->pos[i].x_offset -= buffer->pos[i].x_advance;
+        buffer->pos[i].y_offset -= buffer->pos[i].y_advance;
+      }
       buffer->pos[i].x_advance = 0;
       buffer->pos[i].y_advance = 0;
     }
 }
 
 static inline void
-position_mark (const hb_ot_shape_plan_t *plan,
+position_mark (const hb_ot_shape_plan_t *plan HB_UNUSED,
                hb_font_t *font,
                hb_buffer_t  *buffer,
                hb_glyph_extents_t &base_extents,
@@ -303,7 +309,8 @@
                       hb_font_t *font,
                       hb_buffer_t  *buffer,
                       unsigned int base,
-                      unsigned int end)
+                      unsigned int end,
+                      bool adjust_offsets_when_zeroing)
 {
   hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
 
@@ -314,11 +321,15 @@
                                 &base_extents))
   {
     /* If extents don't work, zero marks and go home. */
-    zero_mark_advances (buffer, base + 1, end);
+    zero_mark_advances (buffer, base + 1, end, adjust_offsets_when_zeroing);
     return;
   }
-  base_extents.x_bearing += buffer->pos[base].x_offset;
   base_extents.y_bearing += buffer->pos[base].y_offset;
+  /* Use horizontal advance for horizontal positioning.
+   * Generally a better idea.  Also works for zero-ink glyphs.  See:
+   * https://github.com/harfbuzz/harfbuzz/issues/1532 */
+  base_extents.x_bearing = 0;
+  base_extents.width = font->get_glyph_h_advance (buffer->info[base].codepoint);
 
   unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
   /* Use integer for num_lig_components such that it doesn't convert to unsigned
@@ -394,7 +405,8 @@
                   hb_font_t *font,
                   hb_buffer_t  *buffer,
                   unsigned int start,
-                  unsigned int end)
+                  unsigned int end,
+                  bool adjust_offsets_when_zeroing)
 {
   if (end - start < 2)
     return;
@@ -410,16 +422,17 @@
         if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[j])))
           break;
 
-      position_around_base (plan, font, buffer, i, j);
+      position_around_base (plan, font, buffer, i, j, adjust_offsets_when_zeroing);
 
       i = j - 1;
     }
 }
 
 void
-_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
-                                hb_font_t *font,
-                                hb_buffer_t  *buffer)
+_hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
+                                     hb_font_t *font,
+                                     hb_buffer_t  *buffer,
+                                     bool adjust_offsets_when_zeroing)
 {
   _hb_buffer_assert_gsubgpos_vars (buffer);
 
@@ -428,81 +441,66 @@
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 1; i < count; i++)
     if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
-      position_cluster (plan, font, buffer, start, i);
+      position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
       start = i;
     }
-  position_cluster (plan, font, buffer, start, count);
+  position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
 }
 
 
-/* Performs old-style TrueType kerning. */
+struct hb_ot_shape_fallback_kern_driver_t
+{
+  hb_ot_shape_fallback_kern_driver_t (hb_font_t   *font_,
+                                      hb_buffer_t *buffer) :
+    font (font_), direction (buffer->props.direction) {}
+
+  hb_position_t get_kerning (hb_codepoint_t first, hb_codepoint_t second) const
+  {
+    hb_position_t kern = 0;
+    font->get_glyph_kerning_for_direction (first, second,
+                                           direction,
+                                           &kern, &kern);
+    return kern;
+  }
+
+  hb_font_t *font;
+  hb_direction_t direction;
+};
+
+/* Performs font-assisted kerning. */
 void
 _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
                             hb_font_t *font,
-                            hb_buffer_t  *buffer)
+                            hb_buffer_t *buffer)
 {
-  if (!plan->has_kern) return;
-
-  OT::hb_ot_apply_context_t c (1, font, buffer);
-  c.set_lookup_mask (plan->kern_mask);
-  c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
-  OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input;
-  skippy_iter.init (&c);
+  if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
+      !font->has_glyph_h_kerning_func () :
+      !font->has_glyph_v_kerning_func ())
+    return;
 
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  for (unsigned int idx = 0; idx < count;)
-  {
-    skippy_iter.reset (idx, 1);
-    if (!skippy_iter.next ())
-    {
-      idx++;
-      continue;
-    }
+  bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
 
-    hb_position_t x_kern, y_kern;
-    font->get_glyph_kerning_for_direction (info[idx].codepoint,
-                                           info[skippy_iter.idx].codepoint,
-                                           buffer->props.direction,
-                                           &x_kern, &y_kern);
+  if (reverse)
+    buffer->reverse ();
 
-    if (x_kern)
-    {
-      hb_position_t kern1 = x_kern >> 1;
-      hb_position_t kern2 = x_kern - kern1;
-      pos[idx].x_advance += kern1;
-      pos[skippy_iter.idx].x_advance += kern2;
-      pos[skippy_iter.idx].x_offset += kern2;
-      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
-    }
+  hb_ot_shape_fallback_kern_driver_t driver (font, buffer);
+  OT::hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t> machine (driver);
+  machine.kern (font, buffer, plan->kern_mask, false);
 
-    if (y_kern)
-    {
-      hb_position_t kern1 = y_kern >> 1;
-      hb_position_t kern2 = y_kern - kern1;
-      pos[idx].y_advance += kern1;
-      pos[skippy_iter.idx].y_advance += kern2;
-      pos[skippy_iter.idx].y_offset += kern2;
-      buffer->unsafe_to_break (idx, skippy_iter.idx + 1);
-    }
-
-    idx = skippy_iter.idx;
-  }
+  if (reverse)
+    buffer->reverse ();
 }
 
 
 /* Adjusts width of various spaces. */
 void
-_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+_hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
                               hb_font_t *font,
                               hb_buffer_t  *buffer)
 {
-  if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
-    return;
-
   hb_glyph_info_t *info = buffer->info;
   hb_glyph_position_t *pos = buffer->pos;
+  bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
   unsigned int count = buffer->len;
   for (unsigned int i = 0; i < count; i++)
     if (_hb_glyph_info_is_unicode_space (&info[i]) && !_hb_glyph_info_ligated (&info[i]))
@@ -523,27 +521,40 @@
         case t::SPACE_EM_5:
         case t::SPACE_EM_6:
         case t::SPACE_EM_16:
-          pos[i].x_advance = (font->x_scale + ((int) space_type)/2) / (int) space_type;
+          if (horizontal)
+            pos[i].x_advance = +(font->x_scale + ((int) space_type)/2) / (int) space_type;
+          else
+            pos[i].y_advance = -(font->y_scale + ((int) space_type)/2) / (int) space_type;
           break;
 
         case t::SPACE_4_EM_18:
-          pos[i].x_advance = (int64_t) font->x_scale * 4 / 18;
+          if (horizontal)
+            pos[i].x_advance = (int64_t) +font->x_scale * 4 / 18;
+          else
+            pos[i].y_advance = (int64_t) -font->y_scale * 4 / 18;
           break;
 
         case t::SPACE_FIGURE:
           for (char u = '0'; u <= '9'; u++)
             if (font->get_nominal_glyph (u, &glyph))
             {
-              pos[i].x_advance = font->get_glyph_h_advance (glyph);
+              if (horizontal)
+                pos[i].x_advance = font->get_glyph_h_advance (glyph);
+              else
+                pos[i].y_advance = font->get_glyph_v_advance (glyph);
               break;
             }
           break;
 
         case t::SPACE_PUNCTUATION:
-          if (font->get_nominal_glyph ('.', &glyph))
-            pos[i].x_advance = font->get_glyph_h_advance (glyph);
-          else if (font->get_nominal_glyph (',', &glyph))
-            pos[i].x_advance = font->get_glyph_h_advance (glyph);
+          if (font->get_nominal_glyph ('.', &glyph) ||
+              font->get_nominal_glyph (',', &glyph))
+          {
+            if (horizontal)
+              pos[i].x_advance = font->get_glyph_h_advance (glyph);
+            else
+              pos[i].y_advance = font->get_glyph_v_advance (glyph);
+          }
           break;
 
         case t::SPACE_NARROW:
@@ -552,7 +563,10 @@
            * However, in my testing, many fonts have their regular space being about that
            * size.  To me, a percentage of the space width makes more sense.  Half is as
            * good as any. */
-          pos[i].x_advance /= 2;
+          if (horizontal)
+            pos[i].x_advance /= 2;
+          else
+            pos[i].y_advance /= 2;
           break;
       }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-fallback.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_FALLBACK_HH
+#define HB_OT_SHAPE_FALLBACK_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape.hh"
+
+
+HB_INTERNAL void _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
+                                                      hb_font_t *font,
+                                                      hb_buffer_t  *buffer,
+                                                      bool adjust_offsets_when_zeroing);
+
+HB_INTERNAL void _hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan,
+                                                                         hb_font_t *font,
+                                                                         hb_buffer_t  *buffer);
+
+
+HB_INTERNAL void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
+                                             hb_font_t *font,
+                                             hb_buffer_t  *buffer);
+
+HB_INTERNAL void _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan,
+                                               hb_font_t *font,
+                                               hb_buffer_t  *buffer);
+
+
+#endif /* HB_OT_SHAPE_FALLBACK_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
-#define HB_OT_SHAPE_NORMALIZE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-/* buffer var allocations, used during the normalization process */
-#define glyph_index()   var1.u32
-
-struct hb_ot_shape_plan_t;
-
-enum hb_ot_shape_normalization_mode_t {
-  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
-  HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* never composes base-to-base */
-  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* always fully decomposes and then recompose back */
-
-  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS
-};
-
-HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,
-                                         hb_buffer_t *buffer,
-                                         hb_font_t *font);
-
-
-struct hb_ot_shape_normalize_context_t
-{
-  const hb_ot_shape_plan_t *plan;
-  hb_buffer_t *buffer;
-  hb_font_t *font;
-  hb_unicode_funcs_t *unicode;
-  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
-                     hb_codepoint_t  ab,
-                     hb_codepoint_t *a,
-                     hb_codepoint_t *b);
-  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
-                   hb_codepoint_t  a,
-                   hb_codepoint_t  b,
-                   hb_codepoint_t *ab);
-};
-
-
-#endif /* HB_OT_SHAPE_NORMALIZE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,9 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-ot-shape-normalize-private.hh"
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-private.hh"
+#include "hb-ot-shape-normalize.hh"
+#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shape.hh"
 
 
 /*
@@ -213,17 +213,19 @@
 }
 
 static inline void
-handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool short_circuit)
+handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
+                                   unsigned int end,
+                                   bool short_circuit HB_UNUSED)
 {
   /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
   hb_buffer_t * const buffer = c->buffer;
   hb_font_t * const font = c->font;
   for (; buffer->idx < end - 1 && buffer->successful;) {
     if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) {
-      /* The next two lines are some ugly lines... But work. */
       if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()))
       {
-        buffer->replace_glyphs (2, 1, &buffer->cur().codepoint);
+        hb_codepoint_t unicode = buffer->cur().codepoint;
+        buffer->replace_glyphs (2, 1, &unicode);
       }
       else
       {
@@ -264,15 +266,6 @@
     decompose_current_character (c, short_circuit);
 }
 
-static inline void
-decompose_cluster (const hb_ot_shape_normalize_context_t *c, unsigned int end, bool might_short_circuit, bool always_short_circuit)
-{
-  if (likely (c->buffer->idx + 1 == end))
-    decompose_current_character (c, might_short_circuit);
-  else
-    decompose_multi_char_cluster (c, end, always_short_circuit);
-}
-
 
 static int
 compare_combining_class (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
@@ -294,6 +287,16 @@
   _hb_buffer_assert_unicode_vars (buffer);
 
   hb_ot_shape_normalization_mode_t mode = plan->shaper->normalization_preference;
+  if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_AUTO)
+  {
+    if (plan->has_gpos_mark)
+      // https://github.com/harfbuzz/harfbuzz/issues/653#issuecomment-423905920
+      //mode = HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED;
+      mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
+    else
+      mode = HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS;
+  }
+
   const hb_ot_shape_normalize_context_t c = {
     plan,
     buffer,
@@ -318,105 +321,81 @@
 
   /* First round, decompose */
 
-  buffer->clear_output ();
-  count = buffer->len;
-  for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
+  bool all_simple = true;
   {
-    unsigned int end;
-    for (end = buffer->idx + 1; end < count; end++)
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
+    buffer->clear_output ();
+    count = buffer->len;
+    buffer->idx = 0;
+    do
+    {
+      unsigned int end;
+      for (end = buffer->idx + 1; end < count; end++)
+        if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end]))))
+          break;
+
+      if (end < count)
+        end--; /* Leave one base for the marks to cluster with. */
+
+      /* From idx to end are simple clusters. */
+      if (might_short_circuit)
+      {
+        unsigned int done = font->get_nominal_glyphs (end - buffer->idx,
+                                                      &buffer->cur().codepoint,
+                                                      sizeof (buffer->info[0]),
+                                                      &buffer->cur().glyph_index(),
+                                                      sizeof (buffer->info[0]));
+        buffer->next_glyphs (done);
+      }
+      while (buffer->idx < end && buffer->successful)
+        decompose_current_character (&c, might_short_circuit);
+
+      if (buffer->idx == count || !buffer->successful)
         break;
 
-    decompose_cluster (&c, end, might_short_circuit, always_short_circuit);
+      all_simple = false;
+
+      /* Find all the marks now. */
+      for (end = buffer->idx + 1; end < count; end++)
+        if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[end])))
+          break;
+
+      /* idx to end is one non-simple cluster. */
+      decompose_multi_char_cluster (&c, end, always_short_circuit);
+    }
+    while (buffer->idx < count && buffer->successful);
+    buffer->swap_buffers ();
   }
-  buffer->swap_buffers ();
 
 
   /* Second round, reorder (inplace) */
 
-  count = buffer->len;
-  for (unsigned int i = 0; i < count; i++)
+  if (!all_simple)
   {
-    if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
-      continue;
-
-    unsigned int end;
-    for (end = i + 1; end < count; end++)
-      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
-        break;
-
-    /* We are going to do a O(n^2).  Only do this if the sequence is short. */
-    if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
-      i = end;
-      continue;
-    }
-
-    buffer->sort (i, end, compare_combining_class);
-
-    if (plan->shaper->reorder_marks)
-      plan->shaper->reorder_marks (plan, buffer, i, end);
-
-    i = end;
-  }
-
-
-  if (mode == HB_OT_SHAPE_NORMALIZATION_MODE_NONE ||
-      mode == HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED)
-    return;
-
-  /* Third round, recompose */
-
-  /* As noted in the comment earlier, we don't try to combine
-   * ccc=0 chars with their previous Starter. */
+    count = buffer->len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]) == 0)
+        continue;
 
-  buffer->clear_output ();
-  count = buffer->len;
-  unsigned int starter = 0;
-  buffer->next_glyph ();
-  while (buffer->idx < count && buffer->successful)
-  {
-    hb_codepoint_t composed, glyph;
-    if (/* We don't try to compose a non-mark character with it's preceding starter.
-         * This is both an optimization to avoid trying to compose every two neighboring
-         * glyphs in most scripts AND a desired feature for Hangul.  Apparently Hangul
-         * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
-        HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
-    {
-      if (/* If there's anything between the starter and this char, they should have CCC
-           * smaller than this character's. */
-          (starter == buffer->out_len - 1 ||
-           info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
-          /* And compose. */
-          c.compose (&c,
-                     buffer->out_info[starter].codepoint,
-                     buffer->cur().codepoint,
-                     &composed) &&
-          /* And the font has glyph for the composite. */
-          font->get_nominal_glyph (composed, &glyph))
-      {
-        /* Composes. */
-        buffer->next_glyph (); /* Copy to out-buffer. */
-        if (unlikely (!buffer->successful))
-          return;
-        buffer->merge_out_clusters (starter, buffer->out_len);
-        buffer->out_len--; /* Remove the second composable. */
-        /* Modify starter and carry on. */
-        buffer->out_info[starter].codepoint = composed;
-        buffer->out_info[starter].glyph_index() = glyph;
-        _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
+      unsigned int end;
+      for (end = i + 1; end < count; end++)
+        if (_hb_glyph_info_get_modified_combining_class (&buffer->info[end]) == 0)
+          break;
 
+      /* We are going to do a O(n^2).  Only do this if the sequence is short. */
+      if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
+        i = end;
         continue;
       }
-    }
 
-    /* Blocked, or doesn't compose. */
-    buffer->next_glyph ();
+      buffer->sort (i, end, compare_combining_class);
 
-    if (info_cc (buffer->prev()) == 0)
-      starter = buffer->out_len - 1;
+      if (plan->shaper->reorder_marks)
+        plan->shaper->reorder_marks (plan, buffer, i, end);
+
+      i = end;
+    }
   }
-  buffer->swap_buffers ();
-
   if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_CGJ)
   {
     /* For all CGJ, check if it prevented any reordering at all.
@@ -430,4 +409,63 @@
         _hb_glyph_info_unhide (&buffer->info[i]);
       }
   }
+
+
+  /* Third round, recompose */
+
+  if (!all_simple &&
+      (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS ||
+       mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT))
+  {
+    /* As noted in the comment earlier, we don't try to combine
+     * ccc=0 chars with their previous Starter. */
+
+    buffer->clear_output ();
+    count = buffer->len;
+    unsigned int starter = 0;
+    buffer->next_glyph ();
+    while (buffer->idx < count && buffer->successful)
+    {
+      hb_codepoint_t composed, glyph;
+      if (/* We don't try to compose a non-mark character with it's preceding starter.
+           * This is both an optimization to avoid trying to compose every two neighboring
+           * glyphs in most scripts AND a desired feature for Hangul.  Apparently Hangul
+           * fonts are not designed to mix-and-match pre-composed syllables and Jamo. */
+          HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->cur())))
+      {
+        if (/* If there's anything between the starter and this char, they should have CCC
+             * smaller than this character's. */
+            (starter == buffer->out_len - 1 ||
+             info_cc (buffer->prev()) < info_cc (buffer->cur())) &&
+            /* And compose. */
+            c.compose (&c,
+                       buffer->out_info[starter].codepoint,
+                       buffer->cur().codepoint,
+                       &composed) &&
+            /* And the font has glyph for the composite. */
+            font->get_nominal_glyph (composed, &glyph))
+        {
+          /* Composes. */
+          buffer->next_glyph (); /* Copy to out-buffer. */
+          if (unlikely (!buffer->successful))
+            return;
+          buffer->merge_out_clusters (starter, buffer->out_len);
+          buffer->out_len--; /* Remove the second composable. */
+          /* Modify starter and carry on. */
+          buffer->out_info[starter].codepoint = composed;
+          buffer->out_info[starter].glyph_index() = glyph;
+          _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer);
+
+          continue;
+        }
+      }
+
+      /* Blocked, or doesn't compose. */
+      buffer->next_glyph ();
+
+      if (info_cc (buffer->prev()) == 0)
+        starter = buffer->out_len - 1;
+    }
+    buffer->swap_buffers ();
+  }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-normalize.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_NORMALIZE_HH
+#define HB_OT_SHAPE_NORMALIZE_HH
+
+#include "hb.hh"
+
+
+/* buffer var allocations, used during the normalization process */
+#define glyph_index()   var1.u32
+
+struct hb_ot_shape_plan_t;
+
+enum hb_ot_shape_normalization_mode_t {
+  HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
+  HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED,
+  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS, /* Never composes base-to-base */
+  HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT, /* Always fully decomposes and then recompose back */
+
+  HB_OT_SHAPE_NORMALIZATION_MODE_AUTO, /* See hb-ot-shape-normalize.cc for logic. */
+  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT = HB_OT_SHAPE_NORMALIZATION_MODE_AUTO
+};
+
+HB_INTERNAL void _hb_ot_shape_normalize (const hb_ot_shape_plan_t *shaper,
+                                         hb_buffer_t *buffer,
+                                         hb_font_t *font);
+
+
+struct hb_ot_shape_normalize_context_t
+{
+  const hb_ot_shape_plan_t *plan;
+  hb_buffer_t *buffer;
+  hb_font_t *font;
+  hb_unicode_funcs_t *unicode;
+  bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+                     hb_codepoint_t  ab,
+                     hb_codepoint_t *a,
+                     hb_codepoint_t *b);
+  bool (*compose) (const hb_ot_shape_normalize_context_t *c,
+                   hb_codepoint_t  a,
+                   hb_codepoint_t  b,
+                   hb_codepoint_t *ab);
+};
+
+
+#endif /* HB_OT_SHAPE_NORMALIZE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright © 2010  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_PRIVATE_HH
-#define HB_OT_SHAPE_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-ot-map-private.hh"
-#include "hb-ot-layout-private.hh"
-
-
-
-struct hb_ot_shape_plan_t
-{
-  hb_segment_properties_t props;
-  const struct hb_ot_complex_shaper_t *shaper;
-  hb_ot_map_t map;
-  const void *data;
-  hb_mask_t rtlm_mask, frac_mask, numr_mask, dnom_mask;
-  hb_mask_t kern_mask;
-  unsigned int has_frac : 1;
-  unsigned int has_kern : 1;
-  unsigned int has_mark : 1;
-
-  inline void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
-  {
-    unsigned int table_index;
-    switch (table_tag) {
-      case HB_OT_TAG_GSUB: table_index = 0; break;
-      case HB_OT_TAG_GPOS: table_index = 1; break;
-      default: return;
-    }
-    map.collect_lookups (table_index, lookups);
-  }
-  inline void substitute (hb_font_t *font, hb_buffer_t *buffer) const { map.substitute (this, font, buffer); }
-  inline void position (hb_font_t *font, hb_buffer_t *buffer) const { map.position (this, font, buffer); }
-
-  void init (void)
-  {
-    memset (this, 0, sizeof (*this));
-    map.init ();
-  }
-  void fini (void) {
-    map.fini ();
-  }
-};
-
-struct hb_ot_shape_planner_t
-{
-  /* In the order that they are filled in. */
-  hb_face_t *face;
-  hb_segment_properties_t props;
-  const struct hb_ot_complex_shaper_t *shaper;
-  hb_ot_map_builder_t map;
-
-  hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) :
-                         face (master_plan->face_unsafe),
-                         props (master_plan->props),
-                         shaper (nullptr),
-                         map (face, &props) {}
-
-  inline void compile (hb_ot_shape_plan_t &plan,
-                       const int          *coords,
-                       unsigned int        num_coords)
-  {
-    plan.props = props;
-    plan.shaper = shaper;
-    map.compile (plan.map, coords, num_coords);
-
-    plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
-    plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
-    plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
-    plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
-
-    plan.kern_mask = plan.map.get_mask (HB_DIRECTION_IS_HORIZONTAL (plan.props.direction) ?
-                                        HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n'));
-
-    plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
-    plan.has_kern = !!plan.kern_mask;
-    plan.has_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
-  }
-
-  private:
-  HB_DISALLOW_COPY_AND_ASSIGN (hb_ot_shape_planner_t);
-};
-
-
-#endif /* HB_OT_SHAPE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,62 +26,246 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER ot
-#define hb_ot_shaper_face_data_t hb_ot_layout_t
-#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
-#include "hb-shaper-impl-private.hh"
-
-#include "hb-ot-shape-private.hh"
-#include "hb-ot-shape-complex-private.hh"
-#include "hb-ot-shape-fallback-private.hh"
-#include "hb-ot-shape-normalize-private.hh"
+#include "hb-shaper-impl.hh"
 
-#include "hb-ot-layout-private.hh"
-#include "hb-unicode-private.hh"
-#include "hb-set-private.hh"
-
-#include "hb-ot-layout-gsubgpos-private.hh"
-//#include "hb-aat-layout-private.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shape-fallback.hh"
+#include "hb-ot-shape-normalize.hh"
 
-static hb_tag_t common_features[] = {
-  HB_TAG('c','c','m','p'),
-  HB_TAG('l','o','c','l'),
-  HB_TAG('m','a','r','k'),
-  HB_TAG('m','k','m','k'),
-  HB_TAG('r','l','i','g'),
-};
+#include "hb-ot-face.hh"
+
+#include "hb-set.hh"
+
+#include "hb-aat-layout.hh"
 
 
-static hb_tag_t horizontal_features[] = {
-  HB_TAG('c','a','l','t'),
-  HB_TAG('c','l','i','g'),
-  HB_TAG('c','u','r','s'),
-  HB_TAG('k','e','r','n'),
-  HB_TAG('l','i','g','a'),
-  HB_TAG('r','c','l','t'),
-};
-
+/**
+ * SECTION:hb-ot-shape
+ * @title: hb-ot-shape
+ * @short_description: OpenType shaping support
+ * @include: hb-ot.h
+ *
+ * Support functions for OpenType shaping related queries.
+ **/
 
 
 static void
 hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
-                              const hb_segment_properties_t  *props,
+                              const hb_feature_t             *user_features,
+                              unsigned int                    num_user_features);
+
+static bool
+_hb_apply_morx (hb_face_t *face)
+{
+  if (hb_options ().aat &&
+      hb_aat_layout_has_substitution (face))
+    return true;
+
+  /* Ignore empty GSUB tables. */
+  return (!hb_ot_layout_has_substitution (face) ||
+          !hb_ot_layout_table_get_script_tags (face,
+                                               HB_OT_TAG_GSUB,
+                                               0, nullptr, nullptr)) &&
+         hb_aat_layout_has_substitution (face);
+}
+
+hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t                     *face,
+                                              const hb_segment_properties_t *props) :
+                                                face (face),
+                                                props (*props),
+                                                map (face, props),
+                                                aat_map (face, props),
+                                                apply_morx (_hb_apply_morx (face))
+{
+  shaper = hb_ot_shape_complex_categorize (this);
+
+  script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
+  script_fallback_mark_positioning = shaper->fallback_position;
+
+  if (apply_morx)
+    shaper = &_hb_ot_complex_shaper_default;
+}
+
+void
+hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
+                                const hb_ot_shape_plan_key_t &key)
+{
+  plan.props = props;
+  plan.shaper = shaper;
+  map.compile (plan.map, key);
+  if (apply_morx)
+    aat_map.compile (plan.aat_map);
+
+  plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
+  plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
+  plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
+  plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
+  plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
+  hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
+                      HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
+  plan.kern_mask = plan.map.get_mask (kern_tag);
+  plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
+
+  plan.requested_kerning = !!plan.kern_mask;
+  plan.requested_tracking = !!plan.trak_mask;
+  bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
+  bool disable_gpos = plan.shaper->gpos_tag &&
+                      plan.shaper->gpos_tag != plan.map.chosen_script[1];
+
+  /*
+   * Decide who provides glyph classes. GDEF or Unicode.
+   */
+
+  if (!hb_ot_layout_has_glyph_classes (face))
+    plan.fallback_glyph_classes = true;
+
+  /*
+   * Decide who does substitutions. GSUB, morx, or fallback.
+   */
+
+  plan.apply_morx = apply_morx;
+
+  /*
+   * Decide who does positioning. GPOS, kerx, kern, or fallback.
+   */
+
+  if (hb_options ().aat && hb_aat_layout_has_positioning (face))
+    plan.apply_kerx = true;
+  else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face))
+    plan.apply_gpos = true;
+  else if (hb_aat_layout_has_positioning (face))
+    plan.apply_kerx = true;
+
+  if (!plan.apply_kerx && !has_gpos_kern)
+  {
+    /* Apparently Apple applies kerx if GPOS kern was not applied. */
+    if (hb_aat_layout_has_positioning (face))
+      plan.apply_kerx = true;
+    else if (hb_ot_layout_has_kerning (face))
+      plan.apply_kern = true;
+  }
+
+  plan.zero_marks = script_zero_marks &&
+                    !plan.apply_kerx &&
+                    (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face));
+  plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
+
+  plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
+                                              !plan.apply_kerx &&
+                                              (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face));
+
+  plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
+                                   script_fallback_mark_positioning;
+
+  /* Currently we always apply trak. */
+  plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
+}
+
+bool
+hb_ot_shape_plan_t::init0 (hb_face_t                     *face,
+                           const hb_shape_plan_key_t     *key)
+{
+  map.init ();
+  aat_map.init ();
+
+  hb_ot_shape_planner_t planner (face,
+                                 &key->props);
+
+  hb_ot_shape_collect_features (&planner,
+                                key->user_features,
+                                key->num_user_features);
+
+  planner.compile (*this, key->ot);
+
+  if (shaper->data_create)
+  {
+    data = shaper->data_create (this);
+    if (unlikely (!data))
+      return false;
+  }
+
+  return true;
+}
+
+void
+hb_ot_shape_plan_t::fini ()
+{
+  if (shaper->data_destroy)
+    shaper->data_destroy (const_cast<void *> (data));
+
+  map.fini ();
+  aat_map.fini ();
+}
+
+void
+hb_ot_shape_plan_t::substitute (hb_font_t   *font,
+                                hb_buffer_t *buffer) const
+{
+  if (unlikely (apply_morx))
+    hb_aat_layout_substitute (this, font, buffer);
+  else
+    map.substitute (this, font, buffer);
+}
+
+void
+hb_ot_shape_plan_t::position (hb_font_t   *font,
+                              hb_buffer_t *buffer) const
+{
+  if (this->apply_gpos)
+    map.position (this, font, buffer);
+  else if (this->apply_kerx)
+    hb_aat_layout_position (this, font, buffer);
+  else if (this->apply_kern)
+    hb_ot_layout_kern (this, font, buffer);
+  else
+    _hb_ot_shape_fallback_kern (this, font, buffer);
+
+  if (this->apply_trak)
+    hb_aat_layout_track (this, font, buffer);
+}
+
+
+static const hb_ot_map_feature_t
+common_features[] =
+{
+  {HB_TAG('c','c','m','p'), F_GLOBAL},
+  {HB_TAG('l','o','c','l'), F_GLOBAL},
+  {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('m','k','m','k'), F_GLOBAL_MANUAL_JOINERS},
+  {HB_TAG('r','l','i','g'), F_GLOBAL},
+};
+
+
+static const hb_ot_map_feature_t
+horizontal_features[] =
+{
+  {HB_TAG('c','a','l','t'), F_GLOBAL},
+  {HB_TAG('c','l','i','g'), F_GLOBAL},
+  {HB_TAG('c','u','r','s'), F_GLOBAL},
+  {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK},
+  {HB_TAG('l','i','g','a'), F_GLOBAL},
+  {HB_TAG('r','c','l','t'), F_GLOBAL},
+};
+
+static void
+hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
                               const hb_feature_t             *user_features,
                               unsigned int                    num_user_features)
 {
   hb_ot_map_builder_t *map = &planner->map;
 
-  map->add_global_bool_feature (HB_TAG('r','v','r','n'));
+  map->enable_feature (HB_TAG('r','v','r','n'));
   map->add_gsub_pause (nullptr);
 
-  switch (props->direction) {
+  switch (planner->props.direction) {
     case HB_DIRECTION_LTR:
-      map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
-      map->add_global_bool_feature (HB_TAG ('l','t','r','m'));
+      map->enable_feature (HB_TAG ('l','t','r','a'));
+      map->enable_feature (HB_TAG ('l','t','r','m'));
       break;
     case HB_DIRECTION_RTL:
-      map->add_global_bool_feature (HB_TAG ('r','t','l','a'));
-      map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE);
+      map->enable_feature (HB_TAG ('r','t','l','a'));
+      map->add_feature (HB_TAG ('r','t','l','m'));
       break;
     case HB_DIRECTION_TTB:
     case HB_DIRECTION_BTT:
@@ -90,39 +274,62 @@
       break;
   }
 
-  map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
-  map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
-  map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
+  /* Automatic fractions. */
+  map->add_feature (HB_TAG ('f','r','a','c'));
+  map->add_feature (HB_TAG ('n','u','m','r'));
+  map->add_feature (HB_TAG ('d','n','o','m'));
+
+  /* Random! */
+  map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
+
+  /* Tracking.  We enable dummy feature here just to allow disabling
+   * AAT 'trak' table using features.
+   * https://github.com/harfbuzz/harfbuzz/issues/1303 */
+  map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
+
+  map->enable_feature (HB_TAG ('H','A','R','F'));
 
   if (planner->shaper->collect_features)
     planner->shaper->collect_features (planner);
 
-  for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
-    map->add_global_bool_feature (common_features[i]);
+  map->enable_feature (HB_TAG ('B','U','Z','Z'));
 
-  if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
+  for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
+    map->add_feature (common_features[i]);
+
+  if (HB_DIRECTION_IS_HORIZONTAL (planner->props.direction))
     for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
-      map->add_feature (horizontal_features[i], 1, F_GLOBAL |
-                        (horizontal_features[i] == HB_TAG('k','e','r','n') ?
-                         F_HAS_FALLBACK : F_NONE));
+      map->add_feature (horizontal_features[i]);
   else
   {
     /* We really want to find a 'vert' feature if there's any in the font, no
      * matter which script/langsys it is listed (or not) under.
      * See various bugs referenced from:
      * https://github.com/harfbuzz/harfbuzz/issues/63 */
-    map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH);
+    map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
+  }
+
+  for (unsigned int i = 0; i < num_user_features; i++)
+  {
+    const hb_feature_t *feature = &user_features[i];
+    map->add_feature (feature->tag,
+                      (feature->start == HB_FEATURE_GLOBAL_START &&
+                       feature->end == HB_FEATURE_GLOBAL_END) ?  F_GLOBAL : F_NONE,
+                      feature->value);
+  }
+
+  if (planner->apply_morx)
+  {
+    hb_aat_map_builder_t *aat_map = &planner->aat_map;
+    for (unsigned int i = 0; i < num_user_features; i++)
+    {
+      const hb_feature_t *feature = &user_features[i];
+      aat_map->add_feature (feature->tag, feature->value);
+    }
   }
 
   if (planner->shaper->override_features)
     planner->shaper->override_features (planner);
-
-  for (unsigned int i = 0; i < num_user_features; i++) {
-    const hb_feature_t *feature = &user_features[i];
-    map->add_feature (feature->tag, feature->value,
-                      (feature->start == 0 && feature->end == (unsigned int) -1) ?
-                       F_GLOBAL : F_NONE);
-  }
 }
 
 
@@ -130,18 +337,17 @@
  * shaper face data
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
+struct hb_ot_face_data_t {};
 
-hb_ot_shaper_face_data_t *
+hb_ot_face_data_t *
 _hb_ot_shaper_face_data_create (hb_face_t *face)
 {
-  return _hb_ot_layout_create (face);
+  return (hb_ot_face_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
+_hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
 {
-  _hb_ot_layout_destroy (data);
 }
 
 
@@ -149,68 +355,17 @@
  * shaper font data
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
+struct hb_ot_font_data_t {};
 
-struct hb_ot_shaper_font_data_t {};
-
-hb_ot_shaper_font_data_t *
+hb_ot_font_data_t *
 _hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
 {
-  return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
+  return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 }
 
 void
-_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
-{
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-hb_ot_shaper_shape_plan_data_t *
-_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
-                                      const hb_feature_t *user_features,
-                                      unsigned int        num_user_features,
-                                      const int          *coords,
-                                      unsigned int        num_coords)
+_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data HB_UNUSED)
 {
-  hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
-  if (unlikely (!plan))
-    return nullptr;
-
-  plan->init ();
-
-  hb_ot_shape_planner_t planner (shape_plan);
-
-  planner.shaper = hb_ot_shape_complex_categorize (&planner);
-
-  hb_ot_shape_collect_features (&planner, &shape_plan->props,
-                                user_features, num_user_features);
-
-  planner.compile (*plan, coords, num_coords);
-
-  if (plan->shaper->data_create) {
-    plan->data = plan->shaper->data_create (plan);
-    if (unlikely (!plan->data)) {
-      free(plan);
-      return nullptr;
-    }
-  }
-
-  return plan;
-}
-
-void
-_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
-{
-  if (plan->shaper->data_destroy)
-    plan->shaper->data_destroy (const_cast<void *> (plan->data));
-
-  plan->fini ();
-
-  free (plan);
 }
 
 
@@ -228,8 +383,6 @@
   unsigned int        num_user_features;
 
   /* Transient stuff */
-  bool fallback_positioning;
-  bool fallback_glyph_classes;
   hb_direction_t target_direction;
 };
 
@@ -243,10 +396,53 @@
 static void
 hb_set_unicode_props (hb_buffer_t *buffer)
 {
+  /* Implement enough of Unicode Graphemes here that shaping
+   * in reverse-direction wouldn't break graphemes.  Namely,
+   * we mark all marks and ZWJ and ZWJ,Extended_Pictographic
+   * sequences as continuations.  The foreach_grapheme()
+   * macro uses this bit.
+   *
+   * https://www.unicode.org/reports/tr29/#Regex_Definitions
+   */
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
+  {
     _hb_glyph_info_set_unicode_props (&info[i], buffer);
+
+    /* Marks are already set as continuation by the above line.
+     * Handle Emoji_Modifier and ZWJ-continuation. */
+    if (unlikely (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
+                  hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F3FBu, 0x1F3FFu)))
+    {
+        _hb_glyph_info_set_continuation (&info[i]);
+    }
+    else if (unlikely (_hb_glyph_info_is_zwj (&info[i])))
+    {
+      _hb_glyph_info_set_continuation (&info[i]);
+      if (i + 1 < count &&
+          _hb_unicode_is_emoji_Extended_Pictographic (info[i + 1].codepoint))
+      {
+        i++;
+        _hb_glyph_info_set_unicode_props (&info[i], buffer);
+        _hb_glyph_info_set_continuation (&info[i]);
+      }
+    }
+    /* Or part of the Other_Grapheme_Extend that is not marks.
+     * As of Unicode 11 that is just:
+     *
+     * 200C          ; Other_Grapheme_Extend # Cf       ZERO WIDTH NON-JOINER
+     * FF9E..FF9F    ; Other_Grapheme_Extend # Lm   [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+     * E0020..E007F  ; Other_Grapheme_Extend # Cf  [96] TAG SPACE..CANCEL TAG
+     *
+     * ZWNJ is special, we don't want to merge it as there's no need, and keeping
+     * it separate results in more granular clusters.  Ignore Katakana for now.
+     * Tags are used for Emoji sub-region flag sequences:
+     * https://github.com/harfbuzz/harfbuzz/issues/1556
+     */
+    else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu)))
+      _hb_glyph_info_set_continuation (&info[i]);
+  }
 }
 
 static void
@@ -254,8 +450,7 @@
 {
   if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
       buffer->context_len[0] ||
-      _hb_glyph_info_get_general_category (&buffer->info[0]) !=
-      HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
+      !_hb_glyph_info_is_unicode_mark (&buffer->info[0]))
     return;
 
   if (!font->has_glyph (0x25CCu))
@@ -274,7 +469,6 @@
   buffer->output_info (info);
   while (buffer->idx < buffer->len && buffer->successful)
     buffer->next_glyph ();
-
   buffer->swap_buffers ();
 }
 
@@ -284,26 +478,12 @@
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
     return;
 
-  /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */
-  unsigned int base = 0;
-  unsigned int count = buffer->len;
-  hb_glyph_info_t *info = buffer->info;
-  for (unsigned int i = 1; i < count; i++)
-  {
-    if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) &&
-                !_hb_glyph_info_is_joiner (&info[i])))
-    {
-      if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-        buffer->merge_clusters (base, i);
-      else
-        buffer->unsafe_to_break (base, i);
-      base = i;
-    }
-  }
   if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
-    buffer->merge_clusters (base, count);
+    foreach_grapheme (buffer, start, end)
+      buffer->merge_clusters (start, end);
   else
-    buffer->unsafe_to_break (base, count);
+    foreach_grapheme (buffer, start, end)
+      buffer->unsafe_to_break (start, end);
 }
 
 static void
@@ -321,25 +501,17 @@
       (HB_DIRECTION_IS_VERTICAL   (direction) &&
        direction != HB_DIRECTION_TTB))
   {
-    /* Same loop as hb_form_clusters().
-     * Since form_clusters() merged clusters already, we don't merge. */
-    unsigned int base = 0;
-    unsigned int count = buffer->len;
-    hb_glyph_info_t *info = buffer->info;
-    for (unsigned int i = 1; i < count; i++)
-    {
-      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
+
+    if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+      foreach_grapheme (buffer, start, end)
       {
-        if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
-          buffer->merge_clusters (base, i);
-        buffer->reverse_range (base, i);
-
-        base = i;
+        buffer->merge_clusters (start, end);
+        buffer->reverse_range (start, end);
       }
-    }
-    if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
-      buffer->merge_clusters (base, count);
-    buffer->reverse_range (base, count);
+    else
+      foreach_grapheme (buffer, start, end)
+        /* form_clusters() merged clusters already, we don't merge. */
+        buffer->reverse_range (start, end);
 
     buffer->reverse ();
 
@@ -348,10 +520,12 @@
 }
 
 
-/* Substitute */
+/*
+ * Substitute
+ */
 
 static inline void
-hb_ot_mirror_chars (hb_ot_shape_context_t *c)
+hb_ot_mirror_chars (const hb_ot_shape_context_t *c)
 {
   if (HB_DIRECTION_IS_FORWARD (c->target_direction))
     return;
@@ -372,7 +546,7 @@
 }
 
 static inline void
-hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
+hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c)
 {
   if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
       !c->plan->has_frac)
@@ -422,7 +596,7 @@
 }
 
 static inline void
-hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
+hb_ot_shape_initialize_masks (const hb_ot_shape_context_t *c)
 {
   hb_ot_map_t *map = &c->plan->map;
   hb_buffer_t *buffer = c->buffer;
@@ -432,7 +606,7 @@
 }
 
 static inline void
-hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
+hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c)
 {
   hb_ot_map_t *map = &c->plan->map;
   hb_buffer_t *buffer = c->buffer;
@@ -454,10 +628,8 @@
 }
 
 static void
-hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
+hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer)
 {
-  hb_buffer_t *buffer = c->buffer;
-
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES))
@@ -473,83 +645,29 @@
 }
 
 static void
-hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
+hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
+                               hb_font_t   *font)
 {
-  hb_buffer_t *buffer = c->buffer;
-
   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
       (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
     return;
 
   unsigned int count = buffer->len;
   hb_glyph_info_t *info = buffer->info;
-  hb_glyph_position_t *pos = buffer->pos;
-  unsigned int i = 0;
-  for (i = 0; i < count; i++)
+
+  hb_codepoint_t invisible = buffer->invisible;
+  if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
+      (invisible || font->get_nominal_glyph (' ', &invisible)))
   {
-    if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
-      break;
-  }
-
-  /* No default-ignorables found; return. */
-  if (i == count)
-    return;
-
-  hb_codepoint_t space;
-  if (!(buffer->flags & HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) &&
-      c->font->get_nominal_glyph (' ', &space))
-  {
-    /* Replace default-ignorables with a zero-advance space glyph. */
-    for (/*continue*/; i < count; i++)
+    /* Replace default-ignorables with a zero-advance invisible glyph. */
+    for (unsigned int i = 0; i < count; i++)
     {
       if (_hb_glyph_info_is_default_ignorable (&info[i]))
-        info[i].codepoint = space;
+        info[i].codepoint = invisible;
     }
   }
   else
-  {
-    /* Merge clusters and delete default-ignorables.
-     * NOTE! We can't use out-buffer as we have positioning data. */
-    unsigned int j = i;
-    for (; i < count; i++)
-    {
-      if (_hb_glyph_info_is_default_ignorable (&info[i]))
-      {
-        /* Merge clusters.
-         * Same logic as buffer->delete_glyph(), but for in-place removal. */
-
-        unsigned int cluster = info[i].cluster;
-        if (i + 1 < count && cluster == info[i + 1].cluster)
-          continue; /* Cluster survives; do nothing. */
-
-        if (j)
-        {
-          /* Merge cluster backward. */
-          if (cluster < info[j - 1].cluster)
-          {
-            unsigned int mask = info[i].mask;
-            unsigned int old_cluster = info[j - 1].cluster;
-            for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
-              buffer->set_cluster (info[k - 1], cluster, mask);
-          }
-          continue;
-        }
-
-        if (i + 1 < count)
-          buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
-
-        continue;
-      }
-
-      if (j != i)
-      {
-        info[j] = info[i];
-        pos[j] = pos[i];
-      }
-      j++;
-    }
-    buffer->len = j;
-  }
+    hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable);
 }
 
 
@@ -566,10 +684,10 @@
 }
 
 static inline void
-hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
+hb_synthesize_glyph_classes (hb_buffer_t *buffer)
 {
-  unsigned int count = c->buffer->len;
-  hb_glyph_info_t *info = c->buffer->info;
+  unsigned int count = buffer->len;
+  hb_glyph_info_t *info = buffer->info;
   for (unsigned int i = 0; i < count; i++)
   {
     hb_ot_layout_glyph_props_flags_t klass;
@@ -592,7 +710,7 @@
 }
 
 static inline void
-hb_ot_substitute_default (hb_ot_shape_context_t *c)
+hb_ot_substitute_default (const hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
 
@@ -605,8 +723,8 @@
   hb_ot_shape_setup_masks (c);
 
   /* This is unfortunate to go here, but necessary... */
-  if (c->fallback_positioning)
-    _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
+  if (c->plan->fallback_mark_positioning)
+    _hb_ot_shape_fallback_mark_position_recategorize_marks (c->plan, c->font, buffer);
 
   hb_ot_map_glyphs_fast (buffer);
 
@@ -614,23 +732,20 @@
 }
 
 static inline void
-hb_ot_substitute_complex (hb_ot_shape_context_t *c)
+hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
 {
   hb_buffer_t *buffer = c->buffer;
 
   hb_ot_layout_substitute_start (c->font, buffer);
 
-  if (!hb_ot_layout_has_glyph_classes (c->face))
-    hb_synthesize_glyph_classes (c);
+  if (c->plan->fallback_glyph_classes)
+    hb_synthesize_glyph_classes (c->buffer);
 
   c->plan->substitute (c->font, buffer);
-
-  /* XXX Call morx instead. */
-  //hb_aat_layout_substitute (c->font, c->buffer);
 }
 
 static inline void
-hb_ot_substitute (hb_ot_shape_context_t *c)
+hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
 {
   hb_ot_substitute_default (c);
 
@@ -639,7 +754,21 @@
   hb_ot_substitute_complex (c);
 }
 
-/* Position */
+static inline void
+hb_ot_substitute_post (const hb_ot_shape_context_t *c)
+{
+  hb_ot_hide_default_ignorables (c->buffer, c->font);
+  if (c->plan->apply_morx)
+    hb_aat_layout_remove_deleted_glyphs (c->buffer);
+
+  if (c->plan->shaper->postprocess_glyphs)
+    c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
+}
+
+
+/*
+ * Position
+ */
 
 static inline void
 adjust_mark_offsets (hb_glyph_position_t *pos)
@@ -670,7 +799,7 @@
 }
 
 static inline void
-hb_ot_position_default (hb_ot_shape_context_t *c)
+hb_ot_position_default (const hb_ot_shape_context_t *c)
 {
   hb_direction_t direction = c->buffer->props.direction;
   unsigned int count = c->buffer->len;
@@ -679,8 +808,8 @@
 
   if (HB_DIRECTION_IS_HORIZONTAL (direction))
   {
-    for (unsigned int i = 0; i < count; i++)
-      pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
+    c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
+                                   &pos[0].x_advance, sizeof(pos[0]));
     /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
     if (c->font->has_glyph_h_origin_func ())
       for (unsigned int i = 0; i < count; i++)
@@ -690,9 +819,10 @@
   }
   else
   {
+    c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
+                                   &pos[0].y_advance, sizeof(pos[0]));
     for (unsigned int i = 0; i < count; i++)
     {
-      pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
       c->font->subtract_glyph_v_origin (info[i].codepoint,
                                         &pos[i].x_offset,
                                         &pos[i].y_offset);
@@ -703,23 +833,22 @@
 }
 
 static inline void
-hb_ot_position_complex (hb_ot_shape_context_t *c)
+hb_ot_position_complex (const hb_ot_shape_context_t *c)
 {
   unsigned int count = c->buffer->len;
   hb_glyph_info_t *info = c->buffer->info;
   hb_glyph_position_t *pos = c->buffer->pos;
 
-  /* If the font has no GPOS, AND, no fallback positioning will
-   * happen, AND, direction is forward, then when zeroing mark
-   * widths, we shift the mark with it, such that the mark
-   * is positioned hanging over the previous glyph.  When
+  /* If the font has no GPOS and direction is forward, then when
+   * zeroing mark widths, we shift the mark with it, such that the
+   * mark is positioned hanging over the previous glyph.  When
    * direction is backward we don't shift and it will end up
    * hanging over the next glyph after the final reordering.
-   * If fallback positinoing happens or GPOS is present, we don't
-   * care.
+   *
+   * Note: If fallback positinoing happens, we don't care about
+   * this as it will be overriden.
    */
-  bool adjust_offsets_when_zeroing = c->fallback_positioning &&
-                                     !c->plan->shaper->fallback_position &&
+  bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
                                      HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
 
   /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
@@ -733,36 +862,39 @@
 
   hb_ot_layout_position_start (c->font, c->buffer);
 
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
+  if (c->plan->zero_marks)
+    switch (c->plan->shaper->zero_width_marks)
+    {
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
+        zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
+        break;
 
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      break;
-  }
+      default:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
+        break;
+    }
 
-  if (likely (!c->fallback_positioning))
-    c->plan->position (c->font, c->buffer);
+  c->plan->position (c->font, c->buffer);
 
-  switch (c->plan->shaper->zero_width_marks)
-  {
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
-      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
-      break;
+  if (c->plan->zero_marks)
+    switch (c->plan->shaper->zero_width_marks)
+    {
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
+        zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
+        break;
 
-    default:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
-      break;
-  }
+      default:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
+      case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
+        break;
+    }
 
-  /* Finishing off GPOS has to follow a certain order. */
+  /* Finish off.  Has to follow a certain order. */
   hb_ot_layout_position_finish_advances (c->font, c->buffer);
-  hb_ot_zero_width_default_ignorables (c);
+  hb_ot_zero_width_default_ignorables (c->buffer);
+  if (c->plan->apply_morx)
+    hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
 
   /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
@@ -771,10 +903,14 @@
       c->font->subtract_glyph_h_origin (info[i].codepoint,
                                         &pos[i].x_offset,
                                         &pos[i].y_offset);
+
+  if (c->plan->fallback_mark_positioning)
+    _hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer,
+                                         adjust_offsets_when_zeroing);
 }
 
 static inline void
-hb_ot_position (hb_ot_shape_context_t *c)
+hb_ot_position (const hb_ot_shape_context_t *c)
 {
   c->buffer->clear_positions ();
 
@@ -782,20 +918,10 @@
 
   hb_ot_position_complex (c);
 
-  if (c->fallback_positioning && c->plan->shaper->fallback_position)
-    _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
-
   if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
     hb_buffer_reverse (c->buffer);
 
-  /* Visual fallback goes here. */
-
-  if (c->fallback_positioning)
-    _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
-
   _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
-
-  //hb_aat_layout_position (c->font, c->buffer);
 }
 
 static inline void
@@ -831,22 +957,17 @@
 {
   c->buffer->deallocate_var_all ();
   c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
+  if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
   {
     c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
                               (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
-  if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
+  if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
   {
     c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
                               (unsigned) HB_BUFFER_MAX_OPS_MIN);
   }
 
-  bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
-  //c->fallback_substitute     = disable_otl || !hb_ot_layout_has_substitution (c->face);
-  c->fallback_positioning    = disable_otl || !hb_ot_layout_has_positioning (c->face);
-  c->fallback_glyph_classes  = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
-
   /* Save the original direction, we use it later. */
   c->target_direction = c->buffer->props.direction;
 
@@ -865,13 +986,9 @@
   if (c->plan->shaper->preprocess_text)
     c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
 
-  hb_ot_substitute (c);
+  hb_ot_substitute_pre (c);
   hb_ot_position (c);
-
-  hb_ot_hide_default_ignorables (c);
-
-  if (c->plan->shaper->postprocess_glyphs)
-    c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
+  hb_ot_substitute_post (c);
 
   hb_propagate_flags (c->buffer);
 
@@ -892,7 +1009,7 @@
               const hb_feature_t *features,
               unsigned int        num_features)
 {
-  hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
+  hb_ot_shape_context_t c = {&shape_plan->ot, font, font->face, buffer, features, num_features};
   hb_ot_shape_internal (&c);
 
   return true;
@@ -909,8 +1026,7 @@
                                   hb_tag_t         table_tag,
                                   hb_set_t        *lookup_indexes /* OUT */)
 {
-  /* XXX Does the first part always succeed? */
-  HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
+  shape_plan->ot.collect_lookups (table_tag, lookup_indexes);
 }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2010  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPE_HH
+#define HB_OT_SHAPE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-map.hh"
+#include "hb-aat-map.hh"
+
+
+struct hb_ot_shape_plan_key_t
+{
+  unsigned int variations_index[2];
+
+  void init (hb_face_t   *face,
+                    const int   *coords,
+                    unsigned int num_coords)
+  {
+    for (unsigned int table_index = 0; table_index < 2; table_index++)
+      hb_ot_layout_table_find_feature_variations (face,
+                                                  table_tags[table_index],
+                                                  coords,
+                                                  num_coords,
+                                                  &variations_index[table_index]);
+  }
+
+  bool equal (const hb_ot_shape_plan_key_t *other)
+  {
+    return 0 == memcmp (this, other, sizeof (*this));
+  }
+};
+
+
+struct hb_shape_plan_key_t;
+
+struct hb_ot_shape_plan_t
+{
+  hb_segment_properties_t props;
+  const struct hb_ot_complex_shaper_t *shaper;
+  hb_ot_map_t map;
+  hb_aat_map_t aat_map;
+  const void *data;
+  hb_mask_t frac_mask, numr_mask, dnom_mask;
+  hb_mask_t rtlm_mask;
+  hb_mask_t kern_mask;
+  hb_mask_t trak_mask;
+
+  bool requested_kerning : 1;
+  bool requested_tracking : 1;
+  bool has_frac : 1;
+  bool has_gpos_mark : 1;
+  bool zero_marks : 1;
+  bool fallback_glyph_classes : 1;
+  bool fallback_mark_positioning : 1;
+  bool adjust_mark_positioning_when_zeroing : 1;
+
+  bool apply_gpos : 1;
+  bool apply_kerx : 1;
+  bool apply_kern : 1;
+  bool apply_morx : 1;
+  bool apply_trak : 1;
+
+  void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
+  {
+    unsigned int table_index;
+    switch (table_tag) {
+      case HB_OT_TAG_GSUB: table_index = 0; break;
+      case HB_OT_TAG_GPOS: table_index = 1; break;
+      default: return;
+    }
+    map.collect_lookups (table_index, lookups);
+  }
+
+  HB_INTERNAL bool init0 (hb_face_t                     *face,
+                          const hb_shape_plan_key_t     *key);
+  HB_INTERNAL void fini ();
+
+  HB_INTERNAL void substitute (hb_font_t *font, hb_buffer_t *buffer) const;
+  HB_INTERNAL void position (hb_font_t *font, hb_buffer_t *buffer) const;
+};
+
+struct hb_shape_plan_t;
+
+struct hb_ot_shape_planner_t
+{
+  /* In the order that they are filled in. */
+  hb_face_t *face;
+  hb_segment_properties_t props;
+  hb_ot_map_builder_t map;
+  hb_aat_map_builder_t aat_map;
+  bool apply_morx : 1;
+  bool script_zero_marks : 1;
+  bool script_fallback_mark_positioning : 1;
+  const struct hb_ot_complex_shaper_t *shaper;
+
+  HB_INTERNAL hb_ot_shape_planner_t (hb_face_t                     *face,
+                                     const hb_segment_properties_t *props);
+
+  HB_INTERNAL void compile (hb_ot_shape_plan_t           &plan,
+                            const hb_ot_shape_plan_key_t &key);
+};
+
+
+#endif /* HB_OT_SHAPE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-stat-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,280 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_OT_STAT_TABLE_HH
+#define HB_OT_STAT_TABLE_HH
+
+#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
+
+/*
+ * STAT -- Style Attributes
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/stat
+ */
+#define HB_OT_TAG_STAT HB_TAG('S','T','A','T')
+
+
+namespace OT {
+
+enum
+{
+  OLDER_SIBLING_FONT_ATTRIBUTE = 0x0001,        /* If set, this axis value table
+                                                 * provides axis value information
+                                                 * that is applicable to other fonts
+                                                 * within the same font family. This
+                                                 * is used if the other fonts were
+                                                 * released earlier and did not include
+                                                 * information about values for some axis.
+                                                 * If newer versions of the other
+                                                 * fonts include the information
+                                                 * themselves and are present,
+                                                 * then this record is ignored. */
+  ELIDABLE_AXIS_VALUE_NAME = 0x0002             /* If set, it indicates that the axis
+                                                 * value represents the “normal” value
+                                                 * for the axis and may be omitted when
+                                                 * composing name strings. */
+  // Reserved = 0xFFFC                          /* Reserved for future use — set to zero. */
+};
+
+struct AxisValueFormat1
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier — set to 1. */
+  HBUINT16      axisIndex;      /* Zero-base index into the axis record array
+                                 * identifying the axis of design variation
+                                 * to which the axis value record applies.
+                                 * Must be less than designAxisCount. */
+  HBUINT16      flags;          /* Flags — see below for details. */
+  NameID        valueNameID;    /* The name ID for entries in the 'name' table
+                                 * that provide a display string for this
+                                 * attribute value. */
+  Fixed         value;          /* A numeric value for this attribute value. */
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct AxisValueFormat2
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier — set to 2. */
+  HBUINT16      axisIndex;      /* Zero-base index into the axis record array
+                                 * identifying the axis of design variation
+                                 * to which the axis value record applies.
+                                 * Must be less than designAxisCount. */
+  HBUINT16      flags;          /* Flags — see below for details. */
+  NameID        valueNameID;    /* The name ID for entries in the 'name' table
+                                 * that provide a display string for this
+                                 * attribute value. */
+  Fixed         nominalValue;   /* A numeric value for this attribute value. */
+  Fixed         rangeMinValue;  /* The minimum value for a range associated
+                                 * with the specified name ID. */
+  Fixed         rangeMaxValue;  /* The maximum value for a range associated
+                                 * with the specified name ID. */
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+struct AxisValueFormat3
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier — set to 3. */
+  HBUINT16      axisIndex;      /* Zero-base index into the axis record array
+                                 * identifying the axis of design variation
+                                 * to which the axis value record applies.
+                                 * Must be less than designAxisCount. */
+  HBUINT16      flags;          /* Flags — see below for details. */
+  NameID        valueNameID;    /* The name ID for entries in the 'name' table
+                                 * that provide a display string for this
+                                 * attribute value. */
+  Fixed         value;          /* A numeric value for this attribute value. */
+  Fixed         linkedValue;    /* The numeric value for a style-linked mapping
+                                 * from this value. */
+  public:
+  DEFINE_SIZE_STATIC (16);
+};
+
+struct AxisValueRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      axisIndex;      /* Zero-base index into the axis record array
+                                 * identifying the axis to which this value
+                                 * applies. Must be less than designAxisCount. */
+  Fixed         value;          /* A numeric value for this attribute value. */
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct AxisValueFormat4
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  HBUINT16      format;         /* Format identifier — set to 4. */
+  HBUINT16      axisCount;      /* The total number of axes contributing to
+                                 * this axis-values combination. */
+  HBUINT16      flags;          /* Flags — see below for details. */
+  NameID        valueNameID;    /* The name ID for entries in the 'name' table
+                                 * that provide a display string for this
+                                 * attribute value. */
+  UnsizedArrayOf<AxisValueRecord>
+                axisValues;     /* Array of AxisValue records that provide the
+                                 * combination of axis values, one for each
+                                 * contributing axis. */
+  public:
+  DEFINE_SIZE_ARRAY (8, axisValues);
+};
+
+struct AxisValue
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (unlikely (c->check_struct (this)))
+      return_trace (false);
+
+    switch (u.format)
+    {
+    case 1:  return_trace (likely (u.format1.sanitize (c)));
+    case 2:  return_trace (likely (u.format2.sanitize (c)));
+    case 3:  return_trace (likely (u.format3.sanitize (c)));
+    case 4:  return_trace (likely (u.format4.sanitize (c)));
+    default: return_trace (true);
+    }
+  }
+
+  protected:
+  union
+  {
+  HBUINT16              format;
+  AxisValueFormat1      format1;
+  AxisValueFormat2      format2;
+  AxisValueFormat3      format3;
+  AxisValueFormat4      format4;
+  } u;
+  public:
+  DEFINE_SIZE_UNION (2, format);
+};
+
+struct StatAxisRecord
+{
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this)));
+  }
+
+  protected:
+  Tag           tag;            /* A tag identifying the axis of design variation. */
+  NameID        nameID;         /* The name ID for entries in the 'name' table that
+                                 * provide a display string for this axis. */
+  HBUINT16      ordering;       /* A value that applications can use to determine
+                                 * primary sorting of face names, or for ordering
+                                 * of descriptors when composing family or face names. */
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct STAT
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (likely (c->check_struct (this) &&
+                          majorVersion == 1 &&
+                          minorVersion > 0 &&
+                          designAxesOffset.sanitize (c, this, designAxisCount) &&
+                          offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
+  }
+
+  protected:
+  HBUINT16      majorVersion;   /* Major version number of the style attributes
+                                 * table — set to 1. */
+  HBUINT16      minorVersion;   /* Minor version number of the style attributes
+                                 * table — set to 2. */
+  HBUINT16      designAxisSize; /* The size in bytes of each axis record. */
+  HBUINT16      designAxisCount;/* The number of design axis records. In a
+                                 * font with an 'fvar' table, this value must be
+                                 * greater than or equal to the axisCount value
+                                 * in the 'fvar' table. In all fonts, must
+                                 * be greater than zero if axisValueCount
+                                 * is greater than zero. */
+  LNNOffsetTo<UnsizedArrayOf<StatAxisRecord> >
+                designAxesOffset;
+                                /* Offset in bytes from the beginning of
+                                 * the STAT table to the start of the design
+                                 * axes array. If designAxisCount is zero,
+                                 * set to zero; if designAxisCount is greater
+                                 * than zero, must be greater than zero. */
+  HBUINT16      axisValueCount; /* The number of axis value tables. */
+  LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue> > >
+                offsetToAxisValueOffsets;
+                                /* Offset in bytes from the beginning of
+                                 * the STAT table to the start of the design
+                                 * axes value offsets array. If axisValueCount
+                                 * is zero, set to zero; if axisValueCount is
+                                 * greater than zero, must be greater than zero. */
+  NameID        elidedFallbackNameID;
+                                /* Name ID used as fallback when projection of
+                                 * names into a particular font model produces
+                                 * a subfamily name containing only elidable
+                                 * elements. */
+  public:
+  DEFINE_SIZE_STATIC (20);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_STAT_TABLE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,2064 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ *   ./gen-tag-table.py languagetags language-subtag-registry
+ *
+ * on files with these headers:
+ *
+ * <meta name="updated_at" content="2018-09-07 07:45 PM" />
+ * File-Date: 2018-08-08
+ */
+
+#ifndef HB_OT_TAG_TABLE_HH
+#define HB_OT_TAG_TABLE_HH
+
+static const LangTag ot_languages[] = {
+  {"aa",        {HB_TAG('A','F','R',' ')}},     /* Afar */
+  {"aae",       {HB_TAG('S','Q','I',' ')}},     /* Arbëreshë Albanian -> Albanian */
+  {"aao",       {HB_TAG('A','R','A',' ')}},     /* Algerian Saharan Arabic -> Arabic */
+  {"aat",       {HB_TAG('S','Q','I',' ')}},     /* Arvanitika Albanian -> Albanian */
+  {"ab",        {HB_TAG('A','B','K',' ')}},     /* Abkhazian */
+  {"abh",       {HB_TAG('A','R','A',' ')}},     /* Tajiki Arabic -> Arabic */
+  {"abq",       {HB_TAG('A','B','A',' ')}},     /* Abaza */
+  {"abv",       {HB_TAG('A','R','A',' ')}},     /* Baharna Arabic -> Arabic */
+  {"acf",       {HB_TAG('F','A','N',' ')}},     /* Saint Lucian Creole French -> French Antillean */
+  {"ach",       {HB_TAG('A','C','H',' ')}},     /* Acoli -> Acholi */
+  {"acm",       {HB_TAG('A','R','A',' ')}},     /* Mesopotamian Arabic -> Arabic */
+  {"acq",       {HB_TAG('A','R','A',' ')}},     /* Ta'izzi-Adeni Arabic -> Arabic */
+  {"acr",       {HB_TAG('A','C','R',' ')}},     /* Achi */
+  {"acw",       {HB_TAG('A','R','A',' ')}},     /* Hijazi Arabic -> Arabic */
+  {"acx",       {HB_TAG('A','R','A',' ')}},     /* Omani Arabic -> Arabic */
+  {"acy",       {HB_TAG('A','R','A',' ')}},     /* Cypriot Arabic -> Arabic */
+  {"ada",       {HB_TAG('D','N','G',' ')}},     /* Adangme -> Dangme */
+  {"adf",       {HB_TAG('A','R','A',' ')}},     /* Dhofari Arabic -> Arabic */
+  {"adp",       {HB_TAG('D','Z','N',' ')}},     /* Adap (retired code) -> Dzongkha */
+  {"ady",       {HB_TAG('A','D','Y',' ')}},     /* Adyghe */
+  {"aeb",       {HB_TAG('A','R','A',' ')}},     /* Tunisian Arabic -> Arabic */
+  {"aec",       {HB_TAG('A','R','A',' ')}},     /* Saidi Arabic -> Arabic */
+  {"af",        {HB_TAG('A','F','K',' ')}},     /* Afrikaans */
+  {"afb",       {HB_TAG('A','R','A',' ')}},     /* Gulf Arabic -> Arabic */
+  {"ahg",       {HB_TAG('A','G','W',' ')}},     /* Qimant -> Agaw */
+  {"aht",       {HB_TAG('A','T','H',' ')}},     /* Ahtena -> Athapaskan */
+  {"aii",       {HB_TAG('S','W','A',' '),       /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
+                 HB_TAG('S','Y','R',' ')}},     /* Assyrian Neo-Aramaic -> Syriac */
+  {"aio",       {HB_TAG('A','I','O',' ')}},     /* Aiton */
+  {"aiw",       {HB_TAG('A','R','I',' ')}},     /* Aari */
+  {"ajp",       {HB_TAG('A','R','A',' ')}},     /* South Levantine Arabic -> Arabic */
+  {"ak",        {HB_TAG('A','K','A',' '),       /* Akan [macrolanguage] */
+                 HB_TAG('T','W','I',' ')}},     /* Akan [macrolanguage] -> Twi */
+  {"aln",       {HB_TAG('S','Q','I',' ')}},     /* Gheg Albanian -> Albanian */
+  {"als",       {HB_TAG('S','Q','I',' ')}},     /* Tosk Albanian -> Albanian */
+  {"alt",       {HB_TAG('A','L','T',' ')}},     /* Southern Altai -> Altai */
+  {"am",        {HB_TAG('A','M','H',' ')}},     /* Amharic */
+  {"amf",       {HB_TAG('H','B','N',' ')}},     /* Hamer-Banna -> Hammer-Banna */
+  {"amw",       {HB_TAG('S','Y','R',' ')}},     /* Western Neo-Aramaic -> Syriac */
+  {"an",        {HB_TAG('A','R','G',' ')}},     /* Aragonese */
+  {"ang",       {HB_TAG('A','N','G',' ')}},     /* Old English (ca. 450-1100) -> Anglo-Saxon */
+  {"apc",       {HB_TAG('A','R','A',' ')}},     /* North Levantine Arabic -> Arabic */
+  {"apd",       {HB_TAG('A','R','A',' ')}},     /* Sudanese Arabic -> Arabic */
+  {"apj",       {HB_TAG('A','T','H',' ')}},     /* Jicarilla Apache -> Athapaskan */
+  {"apk",       {HB_TAG('A','T','H',' ')}},     /* Kiowa Apache -> Athapaskan */
+  {"apl",       {HB_TAG('A','T','H',' ')}},     /* Lipan Apache -> Athapaskan */
+  {"apm",       {HB_TAG('A','T','H',' ')}},     /* Mescalero-Chiricahua Apache -> Athapaskan */
+  {"apw",       {HB_TAG('A','T','H',' ')}},     /* Western Apache -> Athapaskan */
+  {"ar",        {HB_TAG('A','R','A',' ')}},     /* Arabic [macrolanguage] */
+  {"arb",       {HB_TAG('A','R','A',' ')}},     /* Standard Arabic -> Arabic */
+  {"arn",       {HB_TAG('M','A','P',' ')}},     /* Mapudungun */
+  {"arq",       {HB_TAG('A','R','A',' ')}},     /* Algerian Arabic -> Arabic */
+  {"ars",       {HB_TAG('A','R','A',' ')}},     /* Najdi Arabic -> Arabic */
+  {"ary",       {HB_TAG('M','O','R',' ')}},     /* Moroccan Arabic -> Moroccan */
+  {"arz",       {HB_TAG('A','R','A',' ')}},     /* Egyptian Arabic -> Arabic */
+  {"as",        {HB_TAG('A','S','M',' ')}},     /* Assamese */
+  {"ast",       {HB_TAG('A','S','T',' ')}},     /* Asturian */
+  {"ath",       {HB_TAG('A','T','H',' ')}},     /* Athapascan [family] -> Athapaskan */
+  {"atj",       {HB_TAG('R','C','R',' ')}},     /* Atikamekw -> R-Cree */
+  {"atv",       {HB_TAG('A','L','T',' ')}},     /* Northern Altai -> Altai */
+  {"auz",       {HB_TAG('A','R','A',' ')}},     /* Uzbeki Arabic -> Arabic */
+  {"av",        {HB_TAG('A','V','R',' ')}},     /* Avaric -> Avar */
+  {"avl",       {HB_TAG('A','R','A',' ')}},     /* Eastern Egyptian Bedawi Arabic -> Arabic */
+  {"awa",       {HB_TAG('A','W','A',' ')}},     /* Awadhi */
+  {"ay",        {HB_TAG('A','Y','M',' ')}},     /* Aymara [macrolanguage] */
+  {"ayc",       {HB_TAG('A','Y','M',' ')}},     /* Southern Aymara -> Aymara */
+  {"ayh",       {HB_TAG('A','R','A',' ')}},     /* Hadrami Arabic -> Arabic */
+  {"ayl",       {HB_TAG('A','R','A',' ')}},     /* Libyan Arabic -> Arabic */
+  {"ayn",       {HB_TAG('A','R','A',' ')}},     /* Sanaani Arabic -> Arabic */
+  {"ayp",       {HB_TAG('A','R','A',' ')}},     /* North Mesopotamian Arabic -> Arabic */
+  {"ayr",       {HB_TAG('A','Y','M',' ')}},     /* Central Aymara -> Aymara */
+  {"az",        {HB_TAG('A','Z','E',' ')}},     /* Azerbaijani [macrolanguage] */
+  {"azb",       {HB_TAG('A','Z','B',' ')}},     /* South Azerbaijani -> Torki */
+  {"azj",       {HB_TAG('A','Z','E',' ')}},     /* North Azerbaijani -> Azerbaijani */
+  {"ba",        {HB_TAG('B','S','H',' ')}},     /* Bashkir */
+  {"bad",       {HB_TAG('B','A','D','0')}},     /* Banda [family] */
+  {"bai",       {HB_TAG('B','M','L',' ')}},     /* Bamileke [family] */
+  {"bal",       {HB_TAG('B','L','I',' ')}},     /* Baluchi [macrolanguage] */
+  {"ban",       {HB_TAG('B','A','N',' ')}},     /* Balinese */
+  {"bar",       {HB_TAG('B','A','R',' ')}},     /* Bavarian */
+  {"bbc",       {HB_TAG('B','B','C',' ')}},     /* Batak Toba */
+  {"bbz",       {HB_TAG('A','R','A',' ')}},     /* Babalia Creole Arabic -> Arabic */
+  {"bcc",       {HB_TAG('B','L','I',' ')}},     /* Southern Balochi -> Baluchi */
+  {"bci",       {HB_TAG('B','A','U',' ')}},     /* Baoulé -> Baulé */
+  {"bcl",       {HB_TAG('B','I','K',' ')}},     /* Central Bikol -> Bikol */
+  {"bcq",       {HB_TAG('B','C','H',' ')}},     /* Bench */
+  {"bcr",       {HB_TAG('A','T','H',' ')}},     /* Babine -> Athapaskan */
+  {"bdy",       {HB_TAG('B','D','Y',' ')}},     /* Bandjalang */
+  {"be",        {HB_TAG('B','E','L',' ')}},     /* Belarusian -> Belarussian */
+  {"bea",       {HB_TAG('A','T','H',' ')}},     /* Beaver -> Athapaskan */
+  {"beb",       {HB_TAG('B','T','I',' ')}},     /* Bebele -> Beti */
+  {"bem",       {HB_TAG('B','E','M',' ')}},     /* Bemba (Zambia) */
+  {"ber",       {HB_TAG('B','B','R',' ')}},     /* Berber [family] */
+  {"bfq",       {HB_TAG('B','A','D',' ')}},     /* Badaga */
+  {"bft",       {HB_TAG('B','L','T',' ')}},     /* Balti */
+  {"bfu",       {HB_TAG('L','A','H',' ')}},     /* Gahri -> Lahuli */
+  {"bfy",       {HB_TAG('B','A','G',' ')}},     /* Bagheli -> Baghelkhandi */
+  {"bg",        {HB_TAG('B','G','R',' ')}},     /* Bulgarian */
+  {"bgc",       {HB_TAG('B','G','C',' ')}},     /* Haryanvi */
+  {"bgn",       {HB_TAG('B','L','I',' ')}},     /* Western Balochi -> Baluchi */
+  {"bgp",       {HB_TAG('B','L','I',' ')}},     /* Eastern Balochi -> Baluchi */
+  {"bgq",       {HB_TAG('B','G','Q',' ')}},     /* Bagri */
+  {"bgr",       {HB_TAG('Q','I','N',' ')}},     /* Bawm Chin -> Chin */
+  {"bhb",       {HB_TAG('B','H','I',' ')}},     /* Bhili */
+  {"bhi",       {HB_TAG('B','H','I',' ')}},     /* Bhilali -> Bhili */
+  {"bhk",       {HB_TAG('B','I','K',' ')}},     /* Albay Bicolano (retired code) -> Bikol */
+  {"bho",       {HB_TAG('B','H','O',' ')}},     /* Bhojpuri */
+  {"bhr",       {HB_TAG('M','L','G',' ')}},     /* Bara Malagasy -> Malagasy */
+  {"bi",        {HB_TAG('B','I','S',' ')}},     /* Bislama */
+  {"bik",       {HB_TAG('B','I','K',' ')}},     /* Bikol [macrolanguage] */
+  {"bin",       {HB_TAG('E','D','O',' ')}},     /* Edo */
+  {"bjj",       {HB_TAG('B','J','J',' ')}},     /* Kanauji */
+  {"bjn",       {HB_TAG('M','L','Y',' ')}},     /* Banjar -> Malay */
+  {"bjq",       {HB_TAG('M','L','G',' ')}},     /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
+  {"bjt",       {HB_TAG('B','L','N',' ')}},     /* Balanta-Ganja -> Balante */
+  {"bla",       {HB_TAG('B','K','F',' ')}},     /* Siksika -> Blackfoot */
+  {"ble",       {HB_TAG('B','L','N',' ')}},     /* Balanta-Kentohe -> Balante */
+  {"blk",       {HB_TAG('B','L','K',' ')}},     /* Pa'o Karen */
+  {"bln",       {HB_TAG('B','I','K',' ')}},     /* Southern Catanduanes Bikol -> Bikol */
+  {"bm",        {HB_TAG('B','M','B',' ')}},     /* Bambara (Bamanankan) */
+  {"bmm",       {HB_TAG('M','L','G',' ')}},     /* Northern Betsimisaraka Malagasy -> Malagasy */
+  {"bn",        {HB_TAG('B','E','N',' ')}},     /* Bengali */
+  {"bo",        {HB_TAG('T','I','B',' ')}},     /* Tibetan */
+  {"bpy",       {HB_TAG('B','P','Y',' ')}},     /* Bishnupriya -> Bishnupriya Manipuri */
+  {"bqi",       {HB_TAG('L','R','C',' ')}},     /* Bakhtiari -> Luri */
+  {"br",        {HB_TAG('B','R','E',' ')}},     /* Breton */
+  {"bra",       {HB_TAG('B','R','I',' ')}},     /* Braj -> Braj Bhasha */
+  {"brh",       {HB_TAG('B','R','H',' ')}},     /* Brahui */
+  {"brx",       {HB_TAG('B','R','X',' ')}},     /* Bodo (India) */
+  {"bs",        {HB_TAG('B','O','S',' ')}},     /* Bosnian */
+  {"bsk",       {HB_TAG('B','S','K',' ')}},     /* Burushaski */
+  {"btb",       {HB_TAG('B','T','I',' ')}},     /* Beti (Cameroon) (retired code) */
+  {"btj",       {HB_TAG('M','L','Y',' ')}},     /* Bacanese Malay -> Malay */
+  {"bto",       {HB_TAG('B','I','K',' ')}},     /* Rinconada Bikol -> Bikol */
+  {"bts",       {HB_TAG('B','T','S',' ')}},     /* Batak Simalungun */
+  {"bug",       {HB_TAG('B','U','G',' ')}},     /* Buginese -> Bugis */
+  {"bum",       {HB_TAG('B','T','I',' ')}},     /* Bulu (Cameroon) -> Beti */
+  {"bve",       {HB_TAG('M','L','Y',' ')}},     /* Berau Malay -> Malay */
+  {"bvu",       {HB_TAG('M','L','Y',' ')}},     /* Bukit Malay -> Malay */
+  {"bxk",       {HB_TAG('L','U','H',' ')}},     /* Bukusu -> Luyia */
+  {"bxp",       {HB_TAG('B','T','I',' ')}},     /* Bebil -> Beti */
+  {"bxr",       {HB_TAG('R','B','U',' ')}},     /* Russia Buriat -> Russian Buriat */
+  {"byn",       {HB_TAG('B','I','L',' ')}},     /* Bilin -> Bilen */
+  {"byv",       {HB_TAG('B','Y','V',' ')}},     /* Medumba */
+  {"bzc",       {HB_TAG('M','L','G',' ')}},     /* Southern Betsimisaraka Malagasy -> Malagasy */
+  {"ca",        {HB_TAG('C','A','T',' ')}},     /* Catalan */
+  {"caf",       {HB_TAG('C','R','R',' '),       /* Southern Carrier -> Carrier */
+                 HB_TAG('A','T','H',' ')}},     /* Southern Carrier -> Athapaskan */
+  {"cak",       {HB_TAG('C','A','K',' ')}},     /* Kaqchikel */
+  {"cbk",       {HB_TAG('C','B','K',' ')}},     /* Chavacano -> Zamboanga Chavacano */
+  {"cbl",       {HB_TAG('Q','I','N',' ')}},     /* Bualkhaw Chin -> Chin */
+  {"cco",       {HB_TAG('C','C','H','N')}},     /* Comaltepec Chinantec -> Chinantec */
+  {"ccq",       {HB_TAG('A','R','K',' ')}},     /* Chaungtha (retired code) -> Rakhine */
+  {"cdo",       {HB_TAG('Z','H','S',' ')}},     /* Min Dong Chinese -> Chinese Simplified */
+  {"ce",        {HB_TAG('C','H','E',' ')}},     /* Chechen */
+  {"ceb",       {HB_TAG('C','E','B',' ')}},     /* Cebuano */
+  {"cfm",       {HB_TAG('H','A','L',' ')}},     /* Halam (Falam Chin) */
+  {"cgg",       {HB_TAG('C','G','G',' ')}},     /* Chiga */
+  {"ch",        {HB_TAG('C','H','A',' ')}},     /* Chamorro */
+  {"chj",       {HB_TAG('C','C','H','N')}},     /* Ojitlán Chinantec -> Chinantec */
+  {"chk",       {HB_TAG('C','H','K','0')}},     /* Chuukese */
+  {"cho",       {HB_TAG('C','H','O',' ')}},     /* Choctaw */
+  {"chp",       {HB_TAG('C','H','P',' '),       /* Chipewyan */
+                 HB_TAG('S','A','Y',' '),       /* Chipewyan -> Sayisi */
+                 HB_TAG('A','T','H',' ')}},     /* Chipewyan -> Athapaskan */
+  {"chq",       {HB_TAG('C','C','H','N')}},     /* Quiotepec Chinantec -> Chinantec */
+  {"chr",       {HB_TAG('C','H','R',' ')}},     /* Cherokee */
+  {"chy",       {HB_TAG('C','H','Y',' ')}},     /* Cheyenne */
+  {"chz",       {HB_TAG('C','C','H','N')}},     /* Ozumacín Chinantec -> Chinantec */
+  {"ciw",       {HB_TAG('O','J','B',' ')}},     /* Chippewa -> Ojibway */
+  {"cja",       {HB_TAG('C','J','A',' ')}},     /* Western Cham */
+  {"cjm",       {HB_TAG('C','J','M',' ')}},     /* Eastern Cham */
+  {"cjy",       {HB_TAG('Z','H','S',' ')}},     /* Jinyu Chinese -> Chinese Simplified */
+  {"cka",       {HB_TAG('Q','I','N',' ')}},     /* Khumi Awa Chin (retired code) -> Chin */
+  {"ckb",       {HB_TAG('K','U','R',' ')}},     /* Central Kurdish -> Kurdish */
+  {"ckt",       {HB_TAG('C','H','K',' ')}},     /* Chukot -> Chukchi */
+  {"clc",       {HB_TAG('A','T','H',' ')}},     /* Chilcotin -> Athapaskan */
+  {"cld",       {HB_TAG('S','Y','R',' ')}},     /* Chaldean Neo-Aramaic -> Syriac */
+  {"cle",       {HB_TAG('C','C','H','N')}},     /* Lealao Chinantec -> Chinantec */
+  {"cmn",       {HB_TAG('Z','H','S',' ')}},     /* Mandarin Chinese -> Chinese Simplified */
+  {"cmr",       {HB_TAG('Q','I','N',' ')}},     /* Mro-Khimi Chin -> Chin */
+  {"cnb",       {HB_TAG('Q','I','N',' ')}},     /* Chinbon Chin -> Chin */
+  {"cnh",       {HB_TAG('Q','I','N',' ')}},     /* Hakha Chin -> Chin */
+  {"cnk",       {HB_TAG('Q','I','N',' ')}},     /* Khumi Chin -> Chin */
+  {"cnl",       {HB_TAG('C','C','H','N')}},     /* Lalana Chinantec -> Chinantec */
+  {"cnt",       {HB_TAG('C','C','H','N')}},     /* Tepetotutla Chinantec -> Chinantec */
+  {"cnw",       {HB_TAG('Q','I','N',' ')}},     /* Ngawn Chin -> Chin */
+  {"co",        {HB_TAG('C','O','S',' ')}},     /* Corsican */
+  {"coa",       {HB_TAG('M','L','Y',' ')}},     /* Cocos Islands Malay -> Malay */
+  {"cop",       {HB_TAG('C','O','P',' ')}},     /* Coptic */
+  {"coq",       {HB_TAG('A','T','H',' ')}},     /* Coquille -> Athapaskan */
+  {"cpa",       {HB_TAG('C','C','H','N')}},     /* Palantla Chinantec -> Chinantec */
+  {"cpe",       {HB_TAG('C','P','P',' ')}},     /* English-based creoles and pidgins [family] -> Creoles */
+  {"cpf",       {HB_TAG('C','P','P',' ')}},     /* French-based creoles and pidgins [family] -> Creoles */
+  {"cpp",       {HB_TAG('C','P','P',' ')}},     /* Portuguese-based creoles and pidgins [family] -> Creoles */
+  {"cpx",       {HB_TAG('Z','H','S',' ')}},     /* Pu-Xian Chinese -> Chinese Simplified */
+  {"cqd",       {HB_TAG('H','M','N',' ')}},     /* Chuanqiandian Cluster Miao -> Hmong */
+  {"cqu",       {HB_TAG('Q','U','H',' ')}},     /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
+  {"cr",        {HB_TAG('C','R','E',' '),       /* Cree [macrolanguage] */
+                 HB_TAG('Y','C','R',' ')}},     /* Cree [macrolanguage] -> Y-Cree */
+  {"crh",       {HB_TAG('C','R','T',' ')}},     /* Crimean Tatar */
+  {"crj",       {HB_TAG('E','C','R',' ')}},     /* Southern East Cree -> Eastern Cree */
+  {"crk",       {HB_TAG('W','C','R',' ')}},     /* Plains Cree -> West-Cree */
+  {"crl",       {HB_TAG('E','C','R',' ')}},     /* Northern East Cree -> Eastern Cree */
+  {"crm",       {HB_TAG('M','C','R',' '),       /* Moose Cree */
+                 HB_TAG('L','C','R',' ')}},     /* Moose Cree -> L-Cree */
+  {"crp",       {HB_TAG('C','P','P',' ')}},     /* Creoles and pidgins [family] -> Creoles */
+  {"crx",       {HB_TAG('C','R','R',' '),       /* Carrier */
+                 HB_TAG('A','T','H',' ')}},     /* Carrier -> Athapaskan */
+  {"cs",        {HB_TAG('C','S','Y',' ')}},     /* Czech */
+  {"csa",       {HB_TAG('C','C','H','N')}},     /* Chiltepec Chinantec -> Chinantec */
+  {"csb",       {HB_TAG('C','S','B',' ')}},     /* Kashubian */
+  {"csh",       {HB_TAG('Q','I','N',' ')}},     /* Asho Chin -> Chin */
+  {"cso",       {HB_TAG('C','C','H','N')}},     /* Sochiapam Chinantec -> Chinantec */
+  {"csw",       {HB_TAG('N','C','R',' '),       /* Swampy Cree -> N-Cree */
+                 HB_TAG('N','H','C',' ')}},     /* Swampy Cree -> Norway House Cree */
+  {"csy",       {HB_TAG('Q','I','N',' ')}},     /* Siyin Chin -> Chin */
+  {"ctc",       {HB_TAG('A','T','H',' ')}},     /* Chetco -> Athapaskan */
+  {"ctd",       {HB_TAG('Q','I','N',' ')}},     /* Tedim Chin -> Chin */
+  {"cte",       {HB_TAG('C','C','H','N')}},     /* Tepinapa Chinantec -> Chinantec */
+  {"ctg",       {HB_TAG('C','T','G',' ')}},     /* Chittagonian */
+  {"ctl",       {HB_TAG('C','C','H','N')}},     /* Tlacoatzintepec Chinantec -> Chinantec */
+  {"cts",       {HB_TAG('B','I','K',' ')}},     /* Northern Catanduanes Bikol -> Bikol */
+  {"cu",        {HB_TAG('C','S','L',' ')}},     /* Church Slavonic */
+  {"cuc",       {HB_TAG('C','C','H','N')}},     /* Usila Chinantec -> Chinantec */
+  {"cuk",       {HB_TAG('C','U','K',' ')}},     /* San Blas Kuna */
+  {"cv",        {HB_TAG('C','H','U',' ')}},     /* Chuvash */
+  {"cvn",       {HB_TAG('C','C','H','N')}},     /* Valle Nacional Chinantec -> Chinantec */
+  {"cwd",       {HB_TAG('D','C','R',' '),       /* Woods Cree */
+                 HB_TAG('T','C','R',' ')}},     /* Woods Cree -> TH-Cree */
+  {"cy",        {HB_TAG('W','E','L',' ')}},     /* Welsh */
+  {"czh",       {HB_TAG('Z','H','S',' ')}},     /* Huizhou Chinese -> Chinese Simplified */
+  {"czo",       {HB_TAG('Z','H','S',' ')}},     /* Min Zhong Chinese -> Chinese Simplified */
+  {"czt",       {HB_TAG('Q','I','N',' ')}},     /* Zotung Chin -> Chin */
+  {"da",        {HB_TAG('D','A','N',' ')}},     /* Danish */
+  {"dao",       {HB_TAG('Q','I','N',' ')}},     /* Daai Chin -> Chin */
+  {"dap",       {HB_TAG('N','I','S',' ')}},     /* Nisi (India) (retired code) */
+  {"dar",       {HB_TAG('D','A','R',' ')}},     /* Dargwa */
+  {"dax",       {HB_TAG('D','A','X',' ')}},     /* Dayi */
+  {"de",        {HB_TAG('D','E','U',' ')}},     /* German */
+  {"den",       {HB_TAG('S','L','A',' '),       /* Slave (Athapascan) [macrolanguage] -> Slavey */
+                 HB_TAG('A','T','H',' ')}},     /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
+  {"dgo",       {HB_TAG('D','G','O',' ')}},     /* Dogri */
+  {"dgr",       {HB_TAG('A','T','H',' ')}},     /* Dogrib -> Athapaskan */
+  {"dhd",       {HB_TAG('M','A','W',' ')}},     /* Dhundari -> Marwari */
+  {"dhg",       {HB_TAG('D','H','G',' ')}},     /* Dhangu */
+  {"dib",       {HB_TAG('D','N','K',' ')}},     /* South Central Dinka -> Dinka */
+  {"dik",       {HB_TAG('D','N','K',' ')}},     /* Southwestern Dinka -> Dinka */
+  {"din",       {HB_TAG('D','N','K',' ')}},     /* Dinka [macrolanguage] */
+  {"dip",       {HB_TAG('D','N','K',' ')}},     /* Northeastern Dinka -> Dinka */
+  {"diq",       {HB_TAG('D','I','Q',' ')}},     /* Dimli */
+  {"diw",       {HB_TAG('D','N','K',' ')}},     /* Northwestern Dinka -> Dinka */
+  {"dje",       {HB_TAG('D','J','R',' ')}},     /* Zarma */
+  {"djr",       {HB_TAG('D','J','R','0')}},     /* Djambarrpuyngu */
+  {"dks",       {HB_TAG('D','N','K',' ')}},     /* Southeastern Dinka -> Dinka */
+  {"dng",       {HB_TAG('D','U','N',' ')}},     /* Dungan */
+  {"dnj",       {HB_TAG('D','N','J',' ')}},     /* Dan */
+  {"doi",       {HB_TAG('D','G','R',' ')}},     /* Dogri [macrolanguage] */
+  {"drh",       {HB_TAG('M','N','G',' ')}},     /* Darkhat (retired code) -> Mongolian */
+  {"drw",       {HB_TAG('D','R','I',' ')}},     /* Darwazi (retired code) -> Dari */
+  {"dsb",       {HB_TAG('L','S','B',' ')}},     /* Lower Sorbian */
+  {"dty",       {HB_TAG('N','E','P',' ')}},     /* Dotyali -> Nepali */
+  {"duj",       {HB_TAG('D','U','J',' ')}},     /* Dhuwal (retired code) */
+  {"dup",       {HB_TAG('M','L','Y',' ')}},     /* Duano -> Malay */
+  {"dv",        {HB_TAG('D','I','V',' '),       /* Divehi (Dhivehi, Maldivian) */
+                 HB_TAG('D','H','V',' ')}},     /* Divehi (Dhivehi, Maldivian) (deprecated) */
+  {"dwu",       {HB_TAG('D','U','J',' ')}},     /* Dhuwal */
+  {"dwy",       {HB_TAG('D','U','J',' ')}},     /* Dhuwaya -> Dhuwal */
+  {"dyu",       {HB_TAG('J','U','L',' ')}},     /* Dyula -> Jula */
+  {"dz",        {HB_TAG('D','Z','N',' ')}},     /* Dzongkha */
+  {"ee",        {HB_TAG('E','W','E',' ')}},     /* Ewe */
+  {"efi",       {HB_TAG('E','F','I',' ')}},     /* Efik */
+  {"ekk",       {HB_TAG('E','T','I',' ')}},     /* Standard Estonian -> Estonian */
+  {"el",        {HB_TAG('E','L','L',' ')}},     /* Modern Greek (1453-) -> Greek */
+  {"emk",       {HB_TAG('E','M','K',' '),       /* Eastern Maninkakan */
+                 HB_TAG('M','N','K',' ')}},     /* Eastern Maninkakan -> Maninka */
+  {"en",        {HB_TAG('E','N','G',' ')}},     /* English */
+  {"enb",       {HB_TAG('K','A','L',' ')}},     /* Markweeta -> Kalenjin */
+  {"enf",       {HB_TAG('F','N','E',' ')}},     /* Forest Enets -> Forest Nenets */
+  {"enh",       {HB_TAG('T','N','E',' ')}},     /* Tundra Enets -> Tundra Nenets */
+  {"eo",        {HB_TAG('N','T','O',' ')}},     /* Esperanto */
+  {"es",        {HB_TAG('E','S','P',' ')}},     /* Spanish */
+  {"esg",       {HB_TAG('G','O','N',' ')}},     /* Aheri Gondi -> Gondi */
+  {"esi",       {HB_TAG('I','P','K',' ')}},     /* North Alaskan Inupiatun -> Inupiat */
+  {"esk",       {HB_TAG('I','P','K',' ')}},     /* Northwest Alaska Inupiatun -> Inupiat */
+  {"esu",       {HB_TAG('E','S','U',' ')}},     /* Central Yupik */
+  {"et",        {HB_TAG('E','T','I',' ')}},     /* Estonian [macrolanguage] */
+  {"eto",       {HB_TAG('B','T','I',' ')}},     /* Eton (Cameroon) -> Beti */
+  {"eu",        {HB_TAG('E','U','Q',' ')}},     /* Basque */
+  {"eve",       {HB_TAG('E','V','N',' ')}},     /* Even */
+  {"evn",       {HB_TAG('E','V','K',' ')}},     /* Evenki */
+  {"ewo",       {HB_TAG('B','T','I',' ')}},     /* Ewondo -> Beti */
+  {"eyo",       {HB_TAG('K','A','L',' ')}},     /* Keiyo -> Kalenjin */
+  {"fa",        {HB_TAG('F','A','R',' ')}},     /* Persian [macrolanguage] */
+  {"fan",       {HB_TAG('F','A','N','0')}},     /* Fang (Equatorial Guinea) */
+  {"fat",       {HB_TAG('F','A','T',' ')}},     /* Fanti */
+  {"fbl",       {HB_TAG('B','I','K',' ')}},     /* West Albay Bikol -> Bikol */
+  {"ff",        {HB_TAG('F','U','L',' ')}},     /* Fulah [macrolanguage] */
+  {"ffm",       {HB_TAG('F','U','L',' ')}},     /* Maasina Fulfulde -> Fulah */
+  {"fi",        {HB_TAG('F','I','N',' ')}},     /* Finnish */
+  {"fil",       {HB_TAG('P','I','L',' ')}},     /* Filipino */
+  {"fj",        {HB_TAG('F','J','I',' ')}},     /* Fijian */
+  {"flm",       {HB_TAG('H','A','L',' '),       /* Halam (Falam Chin) (retired code) */
+                 HB_TAG('Q','I','N',' ')}},     /* Falam Chin (retired code) -> Chin */
+  {"fmp",       {HB_TAG('F','M','P',' ')}},     /* Fe'fe' */
+  {"fo",        {HB_TAG('F','O','S',' ')}},     /* Faroese */
+  {"fon",       {HB_TAG('F','O','N',' ')}},     /* Fon */
+  {"fr",        {HB_TAG('F','R','A',' ')}},     /* French */
+  {"frc",       {HB_TAG('F','R','C',' ')}},     /* Cajun French */
+  {"frp",       {HB_TAG('F','R','P',' ')}},     /* Arpitan */
+  {"fub",       {HB_TAG('F','U','L',' ')}},     /* Adamawa Fulfulde -> Fulah */
+  {"fuc",       {HB_TAG('F','U','L',' ')}},     /* Pulaar -> Fulah */
+  {"fue",       {HB_TAG('F','U','L',' ')}},     /* Borgu Fulfulde -> Fulah */
+  {"fuf",       {HB_TAG('F','T','A',' ')}},     /* Pular -> Futa */
+  {"fuh",       {HB_TAG('F','U','L',' ')}},     /* Western Niger Fulfulde -> Fulah */
+  {"fui",       {HB_TAG('F','U','L',' ')}},     /* Bagirmi Fulfulde -> Fulah */
+  {"fuq",       {HB_TAG('F','U','L',' ')}},     /* Central-Eastern Niger Fulfulde -> Fulah */
+  {"fur",       {HB_TAG('F','R','L',' ')}},     /* Friulian */
+  {"fuv",       {HB_TAG('F','U','V',' ')}},     /* Nigerian Fulfulde */
+  {"fy",        {HB_TAG('F','R','I',' ')}},     /* Western Frisian -> Frisian */
+  {"ga",        {HB_TAG('I','R','I',' ')}},     /* Irish */
+  {"gaa",       {HB_TAG('G','A','D',' ')}},     /* Ga */
+  {"gag",       {HB_TAG('G','A','G',' ')}},     /* Gagauz */
+  {"gan",       {HB_TAG('Z','H','S',' ')}},     /* Gan Chinese -> Chinese Simplified */
+  {"gax",       {HB_TAG('O','R','O',' ')}},     /* Borana-Arsi-Guji Oromo -> Oromo */
+  {"gaz",       {HB_TAG('O','R','O',' ')}},     /* West Central Oromo -> Oromo */
+  {"gbm",       {HB_TAG('G','A','W',' ')}},     /* Garhwali */
+  {"gce",       {HB_TAG('A','T','H',' ')}},     /* Galice -> Athapaskan */
+  {"gd",        {HB_TAG('G','A','E',' ')}},     /* Scottish Gaelic (Gaelic) */
+  {"gda",       {HB_TAG('R','A','J',' ')}},     /* Gade Lohar -> Rajasthani */
+  {"gez",       {HB_TAG('G','E','Z',' ')}},     /* Geez */
+  {"ggo",       {HB_TAG('G','O','N',' ')}},     /* Southern Gondi (retired code) -> Gondi */
+  {"gih",       {HB_TAG('G','I','H',' ')}},     /* Githabul */
+  {"gil",       {HB_TAG('G','I','L','0')}},     /* Kiribati (Gilbertese) */
+  {"gju",       {HB_TAG('R','A','J',' ')}},     /* Gujari -> Rajasthani */
+  {"gkp",       {HB_TAG('G','K','P',' ')}},     /* Guinea Kpelle -> Kpelle (Guinea) */
+  {"gl",        {HB_TAG('G','A','L',' ')}},     /* Galician */
+  {"gld",       {HB_TAG('N','A','N',' ')}},     /* Nanai */
+  {"glk",       {HB_TAG('G','L','K',' ')}},     /* Gilaki */
+  {"gn",        {HB_TAG('G','U','A',' ')}},     /* Guarani [macrolanguage] */
+  {"gnn",       {HB_TAG('G','N','N',' ')}},     /* Gumatj */
+  {"gno",       {HB_TAG('G','O','N',' ')}},     /* Northern Gondi -> Gondi */
+  {"gnw",       {HB_TAG('G','U','A',' ')}},     /* Western Bolivian Guaraní -> Guarani */
+  {"gog",       {HB_TAG('G','O','G',' ')}},     /* Gogo */
+  {"gom",       {HB_TAG('K','O','K',' ')}},     /* Goan Konkani -> Konkani */
+  {"gon",       {HB_TAG('G','O','N',' ')}},     /* Gondi [macrolanguage] */
+  {"grt",       {HB_TAG('G','R','O',' ')}},     /* Garo */
+  {"gru",       {HB_TAG('S','O','G',' ')}},     /* Kistane -> Sodo Gurage */
+  {"gsw",       {HB_TAG('A','L','S',' ')}},     /* Alsatian */
+  {"gu",        {HB_TAG('G','U','J',' ')}},     /* Gujarati */
+  {"guc",       {HB_TAG('G','U','C',' ')}},     /* Wayuu */
+  {"guf",       {HB_TAG('G','U','F',' ')}},     /* Gupapuyngu */
+  {"gug",       {HB_TAG('G','U','A',' ')}},     /* Paraguayan Guaraní -> Guarani */
+  {"gui",       {HB_TAG('G','U','A',' ')}},     /* Eastern Bolivian Guaraní -> Guarani */
+  {"guk",       {HB_TAG('G','M','Z',' '),       /* Gumuz */
+                 HB_TAG('G','U','K',' ')}},     /* Gumuz (SIL fonts) */
+  {"gun",       {HB_TAG('G','U','A',' ')}},     /* Mbyá Guaraní -> Guarani */
+  {"guz",       {HB_TAG('G','U','Z',' ')}},     /* Gusii */
+  {"gv",        {HB_TAG('M','N','X',' ')}},     /* Manx */
+  {"gwi",       {HB_TAG('A','T','H',' ')}},     /* Gwichʼin -> Athapaskan */
+  {"ha",        {HB_TAG('H','A','U',' ')}},     /* Hausa */
+  {"haa",       {HB_TAG('A','T','H',' ')}},     /* Han -> Athapaskan */
+  {"hae",       {HB_TAG('O','R','O',' ')}},     /* Eastern Oromo -> Oromo */
+  {"hak",       {HB_TAG('Z','H','S',' ')}},     /* Hakka Chinese -> Chinese Simplified */
+  {"har",       {HB_TAG('H','R','I',' ')}},     /* Harari */
+  {"haw",       {HB_TAG('H','A','W',' ')}},     /* Hawaiian */
+  {"hay",       {HB_TAG('H','A','Y',' ')}},     /* Haya */
+  {"haz",       {HB_TAG('H','A','Z',' ')}},     /* Hazaragi */
+  {"he",        {HB_TAG('I','W','R',' ')}},     /* Hebrew */
+  {"hea",       {HB_TAG('H','M','N',' ')}},     /* Northern Qiandong Miao -> Hmong */
+  {"hi",        {HB_TAG('H','I','N',' ')}},     /* Hindi */
+  {"hil",       {HB_TAG('H','I','L',' ')}},     /* Hiligaynon */
+  {"hji",       {HB_TAG('M','L','Y',' ')}},     /* Haji -> Malay */
+  {"hlt",       {HB_TAG('Q','I','N',' ')}},     /* Matu Chin -> Chin */
+  {"hma",       {HB_TAG('H','M','N',' ')}},     /* Southern Mashan Hmong -> Hmong */
+  {"hmc",       {HB_TAG('H','M','N',' ')}},     /* Central Huishui Hmong -> Hmong */
+  {"hmd",       {HB_TAG('H','M','N',' ')}},     /* Large Flowery Miao -> Hmong */
+  {"hme",       {HB_TAG('H','M','N',' ')}},     /* Eastern Huishui Hmong -> Hmong */
+  {"hmg",       {HB_TAG('H','M','N',' ')}},     /* Southwestern Guiyang Hmong -> Hmong */
+  {"hmh",       {HB_TAG('H','M','N',' ')}},     /* Southwestern Huishui Hmong -> Hmong */
+  {"hmi",       {HB_TAG('H','M','N',' ')}},     /* Northern Huishui Hmong -> Hmong */
+  {"hmj",       {HB_TAG('H','M','N',' ')}},     /* Ge -> Hmong */
+  {"hml",       {HB_TAG('H','M','N',' ')}},     /* Luopohe Hmong -> Hmong */
+  {"hmm",       {HB_TAG('H','M','N',' ')}},     /* Central Mashan Hmong -> Hmong */
+  {"hmn",       {HB_TAG('H','M','N',' ')}},     /* Hmong [macrolanguage] */
+  {"hmp",       {HB_TAG('H','M','N',' ')}},     /* Northern Mashan Hmong -> Hmong */
+  {"hmq",       {HB_TAG('H','M','N',' ')}},     /* Eastern Qiandong Miao -> Hmong */
+  {"hms",       {HB_TAG('H','M','N',' ')}},     /* Southern Qiandong Miao -> Hmong */
+  {"hmw",       {HB_TAG('H','M','N',' ')}},     /* Western Mashan Hmong -> Hmong */
+  {"hmy",       {HB_TAG('H','M','N',' ')}},     /* Southern Guiyang Hmong -> Hmong */
+  {"hmz",       {HB_TAG('H','M','N',' ')}},     /* Hmong Shua -> Hmong */
+  {"hnd",       {HB_TAG('H','N','D',' ')}},     /* Southern Hindko -> Hindko */
+  {"hne",       {HB_TAG('C','H','H',' ')}},     /* Chhattisgarhi -> Chattisgarhi */
+  {"hnj",       {HB_TAG('H','M','N',' ')}},     /* Hmong Njua -> Hmong */
+  {"hno",       {HB_TAG('H','N','D',' ')}},     /* Northern Hindko -> Hindko */
+  {"ho",        {HB_TAG('H','M','O',' ')}},     /* Hiri Motu */
+  {"hoc",       {HB_TAG('H','O',' ',' ')}},     /* Ho */
+  {"hoi",       {HB_TAG('A','T','H',' ')}},     /* Holikachuk -> Athapaskan */
+  {"hoj",       {HB_TAG('H','A','R',' ')}},     /* Hadothi -> Harauti */
+  {"hr",        {HB_TAG('H','R','V',' ')}},     /* Croatian */
+  {"hrm",       {HB_TAG('H','M','N',' ')}},     /* Horned Miao -> Hmong */
+  {"hsb",       {HB_TAG('U','S','B',' ')}},     /* Upper Sorbian */
+  {"hsn",       {HB_TAG('Z','H','S',' ')}},     /* Xiang Chinese -> Chinese Simplified */
+  {"ht",        {HB_TAG('H','A','I',' ')}},     /* Haitian (Haitian Creole) */
+  {"hu",        {HB_TAG('H','U','N',' ')}},     /* Hungarian */
+  {"huj",       {HB_TAG('H','M','N',' ')}},     /* Northern Guiyang Hmong -> Hmong */
+  {"hup",       {HB_TAG('A','T','H',' ')}},     /* Hupa -> Athapaskan */
+  {"hy",        {HB_TAG('H','Y','E','0'),       /* Armenian -> Armenian East */
+                 HB_TAG('H','Y','E',' ')}},     /* Armenian */
+  {"hyw",       {HB_TAG('H','Y','E',' ')}},     /* Western Armenian -> Armenian */
+  {"hz",        {HB_TAG('H','E','R',' ')}},     /* Herero */
+  {"ia",        {HB_TAG('I','N','A',' ')}},     /* Interlingua (International Auxiliary Language Association) */
+  {"iba",       {HB_TAG('I','B','A',' ')}},     /* Iban */
+  {"ibb",       {HB_TAG('I','B','B',' ')}},     /* Ibibio */
+  {"id",        {HB_TAG('I','N','D',' ')}},     /* Indonesian */
+  {"ida",       {HB_TAG('L','U','H',' ')}},     /* Idakho-Isukha-Tiriki -> Luyia */
+  {"ie",        {HB_TAG('I','L','E',' ')}},     /* Interlingue */
+  {"ig",        {HB_TAG('I','B','O',' ')}},     /* Igbo */
+  {"igb",       {HB_TAG('E','B','I',' ')}},     /* Ebira */
+  {"ii",        {HB_TAG('Y','I','M',' ')}},     /* Sichuan Yi -> Yi Modern */
+  {"ijc",       {HB_TAG('I','J','O',' ')}},     /* Izon -> Ijo */
+  {"ijo",       {HB_TAG('I','J','O',' ')}},     /* Ijo [family] */
+  {"ik",        {HB_TAG('I','P','K',' ')}},     /* Inupiaq [macrolanguage] -> Inupiat */
+  {"ike",       {HB_TAG('I','N','U',' ')}},     /* Eastern Canadian Inuktitut -> Inuktitut */
+  {"ikt",       {HB_TAG('I','N','U',' ')}},     /* Inuinnaqtun -> Inuktitut */
+  {"ilo",       {HB_TAG('I','L','O',' ')}},     /* Iloko -> Ilokano */
+  {"in",        {HB_TAG('I','N','D',' ')}},     /* Indonesian (retired code) */
+  {"ing",       {HB_TAG('A','T','H',' ')}},     /* Degexit'an -> Athapaskan */
+  {"inh",       {HB_TAG('I','N','G',' ')}},     /* Ingush */
+  {"io",        {HB_TAG('I','D','O',' ')}},     /* Ido */
+  {"is",        {HB_TAG('I','S','L',' ')}},     /* Icelandic */
+  {"it",        {HB_TAG('I','T','A',' ')}},     /* Italian */
+  {"iu",        {HB_TAG('I','N','U',' ')}},     /* Inuktitut [macrolanguage] */
+  {"iw",        {HB_TAG('I','W','R',' ')}},     /* Hebrew (retired code) */
+  {"ja",        {HB_TAG('J','A','N',' ')}},     /* Japanese */
+  {"jak",       {HB_TAG('M','L','Y',' ')}},     /* Jakun -> Malay */
+  {"jam",       {HB_TAG('J','A','M',' ')}},     /* Jamaican Creole English -> Jamaican Creole */
+  {"jax",       {HB_TAG('M','L','Y',' ')}},     /* Jambi Malay -> Malay */
+  {"jbo",       {HB_TAG('J','B','O',' ')}},     /* Lojban */
+  {"jct",       {HB_TAG('J','C','T',' ')}},     /* Krymchak */
+  {"ji",        {HB_TAG('J','I','I',' ')}},     /* Yiddish (retired code) */
+  {"jv",        {HB_TAG('J','A','V',' ')}},     /* Javanese */
+  {"jw",        {HB_TAG('J','A','V',' ')}},     /* Javanese (retired code) */
+  {"ka",        {HB_TAG('K','A','T',' ')}},     /* Georgian */
+  {"kaa",       {HB_TAG('K','R','K',' ')}},     /* Kara-Kalpak -> Karakalpak */
+  {"kab",       {HB_TAG('K','A','B','0')}},     /* Kabyle */
+  {"kam",       {HB_TAG('K','M','B',' ')}},     /* Kamba (Kenya) */
+  {"kar",       {HB_TAG('K','R','N',' ')}},     /* Karen [family] */
+  {"kbd",       {HB_TAG('K','A','B',' ')}},     /* Kabardian */
+  {"kby",       {HB_TAG('K','N','R',' ')}},     /* Manga Kanuri -> Kanuri */
+  {"kca",       {HB_TAG('K','H','K',' '),       /* Khanty -> Khanty-Kazim */
+                 HB_TAG('K','H','S',' '),       /* Khanty -> Khanty-Shurishkar */
+                 HB_TAG('K','H','V',' ')}},     /* Khanty -> Khanty-Vakhi */
+  {"kde",       {HB_TAG('K','D','E',' ')}},     /* Makonde */
+  {"kdr",       {HB_TAG('K','R','M',' ')}},     /* Karaim */
+  {"kdt",       {HB_TAG('K','U','Y',' ')}},     /* Kuy */
+  {"kea",       {HB_TAG('K','E','A',' ')}},     /* Kabuverdianu (Crioulo) */
+  {"kek",       {HB_TAG('K','E','K',' ')}},     /* Kekchi */
+  {"kex",       {HB_TAG('K','K','N',' ')}},     /* Kukna -> Kokni */
+  {"kfa",       {HB_TAG('K','O','D',' ')}},     /* Kodava -> Kodagu */
+  {"kfr",       {HB_TAG('K','A','C',' ')}},     /* Kachhi -> Kachchi */
+  {"kfx",       {HB_TAG('K','U','L',' ')}},     /* Kullu Pahari -> Kulvi */
+  {"kfy",       {HB_TAG('K','M','N',' ')}},     /* Kumaoni */
+  {"kg",        {HB_TAG('K','O','N','0')}},     /* Kongo [macrolanguage] */
+  {"kha",       {HB_TAG('K','S','I',' ')}},     /* Khasi */
+  {"khb",       {HB_TAG('X','B','D',' ')}},     /* Lü */
+  {"khk",       {HB_TAG('M','N','G',' ')}},     /* Halh Mongolian -> Mongolian */
+  {"kht",       {HB_TAG('K','H','N',' '),       /* Khamti -> Khamti Shan (Microsoft fonts) */
+                 HB_TAG('K','H','T',' ')}},     /* Khamti -> Khamti Shan (OpenType spec and SIL fonts) */
+  {"khw",       {HB_TAG('K','H','W',' ')}},     /* Khowar */
+  {"ki",        {HB_TAG('K','I','K',' ')}},     /* Kikuyu (Gikuyu) */
+  {"kiu",       {HB_TAG('K','I','U',' ')}},     /* Kirmanjki */
+  {"kj",        {HB_TAG('K','U','A',' ')}},     /* Kuanyama */
+  {"kjd",       {HB_TAG('K','J','D',' ')}},     /* Southern Kiwai */
+  {"kjh",       {HB_TAG('K','H','A',' ')}},     /* Khakas -> Khakass */
+  {"kjp",       {HB_TAG('K','J','P',' ')}},     /* Pwo Eastern Karen -> Eastern Pwo Karen */
+  {"kjz",       {HB_TAG('K','J','Z',' ')}},     /* Bumthangkha */
+  {"kk",        {HB_TAG('K','A','Z',' ')}},     /* Kazakh */
+  {"kkz",       {HB_TAG('A','T','H',' ')}},     /* Kaska -> Athapaskan */
+  {"kl",        {HB_TAG('G','R','N',' ')}},     /* Greenlandic */
+  {"kln",       {HB_TAG('K','A','L',' ')}},     /* Kalenjin [macrolanguage] */
+  {"km",        {HB_TAG('K','H','M',' ')}},     /* Khmer */
+  {"kmb",       {HB_TAG('M','B','N',' ')}},     /* Kimbundu -> Mbundu */
+  {"kmr",       {HB_TAG('K','U','R',' ')}},     /* Northern Kurdish -> Kurdish */
+  {"kmw",       {HB_TAG('K','M','O',' ')}},     /* Komo (Democratic Republic of Congo) */
+  {"kmz",       {HB_TAG('K','M','Z',' ')}},     /* Khorasani Turkish -> Khorasani Turkic */
+  {"kn",        {HB_TAG('K','A','N',' ')}},     /* Kannada */
+  {"knc",       {HB_TAG('K','N','R',' ')}},     /* Central Kanuri -> Kanuri */
+  {"kng",       {HB_TAG('K','O','N','0')}},     /* Koongo -> Kongo */
+  {"knn",       {HB_TAG('K','O','K',' ')}},     /* Konkani */
+  {"ko",        {HB_TAG('K','O','R',' ')}},     /* Korean */
+  {"koi",       {HB_TAG('K','O','P',' ')}},     /* Komi-Permyak */
+  {"kok",       {HB_TAG('K','O','K',' ')}},     /* Konkani [macrolanguage] */
+  {"kos",       {HB_TAG('K','O','S',' ')}},     /* Kosraean */
+  {"koy",       {HB_TAG('A','T','H',' ')}},     /* Koyukon -> Athapaskan */
+  {"kpe",       {HB_TAG('K','P','L',' ')}},     /* Kpelle [macrolanguage] */
+  {"kpv",       {HB_TAG('K','O','Z',' ')}},     /* Komi-Zyrian */
+  {"kpy",       {HB_TAG('K','Y','K',' ')}},     /* Koryak */
+  {"kqs",       {HB_TAG('K','I','S',' ')}},     /* Northern Kissi -> Kisii */
+  {"kqy",       {HB_TAG('K','R','T',' ')}},     /* Koorete */
+  {"kr",        {HB_TAG('K','N','R',' ')}},     /* Kanuri [macrolanguage] */
+  {"krc",       {HB_TAG('K','A','R',' '),       /* Karachay-Balkar -> Karachay */
+                 HB_TAG('B','A','L',' ')}},     /* Karachay-Balkar -> Balkar */
+  {"kri",       {HB_TAG('K','R','I',' ')}},     /* Krio */
+  {"krl",       {HB_TAG('K','R','L',' ')}},     /* Karelian */
+  {"krt",       {HB_TAG('K','N','R',' ')}},     /* Tumari Kanuri -> Kanuri */
+  {"kru",       {HB_TAG('K','U','U',' ')}},     /* Kurukh */
+  {"ks",        {HB_TAG('K','S','H',' ')}},     /* Kashmiri */
+  {"ksh",       {HB_TAG('K','S','H','0')}},     /* Kölsch -> Ripuarian */
+  {"kss",       {HB_TAG('K','I','S',' ')}},     /* Southern Kisi -> Kisii */
+  {"ksw",       {HB_TAG('K','S','W',' ')}},     /* S’gaw Karen */
+  {"ktb",       {HB_TAG('K','E','B',' ')}},     /* Kambaata -> Kebena */
+  {"ktu",       {HB_TAG('K','O','N',' ')}},     /* Kituba (Democratic Republic of Congo) -> Kikongo */
+  {"ktw",       {HB_TAG('A','T','H',' ')}},     /* Kato -> Athapaskan */
+  {"ku",        {HB_TAG('K','U','R',' ')}},     /* Kurdish [macrolanguage] */
+  {"kum",       {HB_TAG('K','U','M',' ')}},     /* Kumyk */
+  {"kuu",       {HB_TAG('A','T','H',' ')}},     /* Upper Kuskokwim -> Athapaskan */
+  {"kv",        {HB_TAG('K','O','M',' ')}},     /* Komi [macrolanguage] */
+  {"kvb",       {HB_TAG('M','L','Y',' ')}},     /* Kubu -> Malay */
+  {"kvr",       {HB_TAG('M','L','Y',' ')}},     /* Kerinci -> Malay */
+  {"kw",        {HB_TAG('C','O','R',' ')}},     /* Cornish */
+  {"kwy",       {HB_TAG('K','O','N','0')}},     /* San Salvador Kongo -> Kongo */
+  {"kxc",       {HB_TAG('K','M','S',' ')}},     /* Konso -> Komso */
+  {"kxd",       {HB_TAG('M','L','Y',' ')}},     /* Brunei -> Malay */
+  {"kxu",       {HB_TAG('K','U','I',' ')}},     /* Kui (India) */
+  {"ky",        {HB_TAG('K','I','R',' ')}},     /* Kirghiz (Kyrgyz) */
+  {"kyu",       {HB_TAG('K','Y','U',' ')}},     /* Western Kayah */
+  {"la",        {HB_TAG('L','A','T',' ')}},     /* Latin */
+  {"lad",       {HB_TAG('J','U','D',' ')}},     /* Ladino */
+  {"lb",        {HB_TAG('L','T','Z',' ')}},     /* Luxembourgish */
+  {"lbe",       {HB_TAG('L','A','K',' ')}},     /* Lak */
+  {"lbj",       {HB_TAG('L','D','K',' ')}},     /* Ladakhi */
+  {"lbl",       {HB_TAG('B','I','K',' ')}},     /* Libon Bikol -> Bikol */
+  {"lce",       {HB_TAG('M','L','Y',' ')}},     /* Loncong -> Malay */
+  {"lcf",       {HB_TAG('M','L','Y',' ')}},     /* Lubu -> Malay */
+  {"ldi",       {HB_TAG('K','O','N','0')}},     /* Laari -> Kongo */
+  {"lez",       {HB_TAG('L','E','Z',' ')}},     /* Lezghian -> Lezgi */
+  {"lg",        {HB_TAG('L','U','G',' ')}},     /* Ganda */
+  {"li",        {HB_TAG('L','I','M',' ')}},     /* Limburgish */
+  {"lif",       {HB_TAG('L','M','B',' ')}},     /* Limbu */
+  {"lij",       {HB_TAG('L','I','J',' ')}},     /* Ligurian */
+  {"lis",       {HB_TAG('L','I','S',' ')}},     /* Lisu */
+  {"liw",       {HB_TAG('M','L','Y',' ')}},     /* Col -> Malay */
+  {"ljp",       {HB_TAG('L','J','P',' ')}},     /* Lampung Api -> Lampung */
+  {"lkb",       {HB_TAG('L','U','H',' ')}},     /* Kabras -> Luyia */
+  {"lki",       {HB_TAG('L','K','I',' ')}},     /* Laki */
+  {"lko",       {HB_TAG('L','U','H',' ')}},     /* Khayo -> Luyia */
+  {"lks",       {HB_TAG('L','U','H',' ')}},     /* Kisa -> Luyia */
+  {"lld",       {HB_TAG('L','A','D',' ')}},     /* Ladin */
+  {"lmn",       {HB_TAG('L','A','M',' ')}},     /* Lambadi -> Lambani */
+  {"lmo",       {HB_TAG('L','M','O',' ')}},     /* Lombard */
+  {"ln",        {HB_TAG('L','I','N',' ')}},     /* Lingala */
+  {"lo",        {HB_TAG('L','A','O',' ')}},     /* Lao */
+  {"lom",       {HB_TAG('L','O','M',' ')}},     /* Loma (Liberia) */
+  {"lrc",       {HB_TAG('L','R','C',' ')}},     /* Northern Luri -> Luri */
+  {"lri",       {HB_TAG('L','U','H',' ')}},     /* Marachi -> Luyia */
+  {"lrm",       {HB_TAG('L','U','H',' ')}},     /* Marama -> Luyia */
+  {"lsm",       {HB_TAG('L','U','H',' ')}},     /* Saamia -> Luyia */
+  {"lt",        {HB_TAG('L','T','H',' ')}},     /* Lithuanian */
+  {"ltg",       {HB_TAG('L','V','I',' ')}},     /* Latgalian -> Latvian */
+  {"lto",       {HB_TAG('L','U','H',' ')}},     /* Tsotso -> Luyia */
+  {"lts",       {HB_TAG('L','U','H',' ')}},     /* Tachoni -> Luyia */
+  {"lu",        {HB_TAG('L','U','B',' ')}},     /* Luba-Katanga */
+  {"lua",       {HB_TAG('L','U','A',' ')}},     /* Luba-Lulua */
+  {"luo",       {HB_TAG('L','U','O',' ')}},     /* Luo (Kenya and Tanzania) */
+  {"lus",       {HB_TAG('M','I','Z',' ')}},     /* Lushai -> Mizo */
+  {"luy",       {HB_TAG('L','U','H',' ')}},     /* Luyia [macrolanguage] */
+  {"luz",       {HB_TAG('L','R','C',' ')}},     /* Southern Luri -> Luri */
+  {"lv",        {HB_TAG('L','V','I',' ')}},     /* Latvian [macrolanguage] */
+  {"lvs",       {HB_TAG('L','V','I',' ')}},     /* Standard Latvian -> Latvian */
+  {"lwg",       {HB_TAG('L','U','H',' ')}},     /* Wanga -> Luyia */
+  {"lzh",       {HB_TAG('Z','H','T',' ')}},     /* Literary Chinese -> Chinese Traditional */
+  {"lzz",       {HB_TAG('L','A','Z',' ')}},     /* Laz */
+  {"mad",       {HB_TAG('M','A','D',' ')}},     /* Madurese -> Madura */
+  {"mag",       {HB_TAG('M','A','G',' ')}},     /* Magahi */
+  {"mai",       {HB_TAG('M','T','H',' ')}},     /* Maithili */
+  {"mak",       {HB_TAG('M','K','R',' ')}},     /* Makasar */
+  {"mam",       {HB_TAG('M','A','M',' ')}},     /* Mam */
+  {"man",       {HB_TAG('M','N','K',' ')}},     /* Mandingo [macrolanguage] -> Maninka */
+  {"max",       {HB_TAG('M','L','Y',' ')}},     /* North Moluccan Malay -> Malay */
+  {"mbo",       {HB_TAG('M','B','O',' ')}},     /* Mbo (Cameroon) */
+  {"mct",       {HB_TAG('B','T','I',' ')}},     /* Mengisa -> Beti */
+  {"mdf",       {HB_TAG('M','O','K',' ')}},     /* Moksha */
+  {"mdr",       {HB_TAG('M','D','R',' ')}},     /* Mandar */
+  {"mdy",       {HB_TAG('M','L','E',' ')}},     /* Male (Ethiopia) */
+  {"men",       {HB_TAG('M','D','E',' ')}},     /* Mende (Sierra Leone) */
+  {"meo",       {HB_TAG('M','L','Y',' ')}},     /* Kedah Malay -> Malay */
+  {"mer",       {HB_TAG('M','E','R',' ')}},     /* Meru */
+  {"mfa",       {HB_TAG('M','F','A',' ')}},     /* Pattani Malay */
+  {"mfb",       {HB_TAG('M','L','Y',' ')}},     /* Bangka -> Malay */
+  {"mfe",       {HB_TAG('M','F','E',' ')}},     /* Morisyen */
+  {"mg",        {HB_TAG('M','L','G',' ')}},     /* Malagasy [macrolanguage] */
+  {"mh",        {HB_TAG('M','A','H',' ')}},     /* Marshallese */
+  {"mhr",       {HB_TAG('L','M','A',' ')}},     /* Eastern Mari -> Low Mari */
+  {"mhv",       {HB_TAG('A','R','K',' ')}},     /* Arakanese (retired code) -> Rakhine */
+  {"mi",        {HB_TAG('M','R','I',' ')}},     /* Maori */
+  {"min",       {HB_TAG('M','I','N',' ')}},     /* Minangkabau */
+  {"mk",        {HB_TAG('M','K','D',' ')}},     /* Macedonian */
+  {"mku",       {HB_TAG('M','N','K',' ')}},     /* Konyanka Maninka -> Maninka */
+  {"mkw",       {HB_TAG('M','K','W',' ')}},     /* Kituba (Congo) */
+  {"ml",        {HB_TAG('M','A','L',' '),       /* Malayalam -> Malayalam Traditional */
+                 HB_TAG('M','L','R',' ')}},     /* Malayalam -> Malayalam Reformed */
+  {"mlq",       {HB_TAG('M','L','N',' '),       /* Western Maninkakan -> Malinke */
+                 HB_TAG('M','N','K',' ')}},     /* Western Maninkakan -> Maninka */
+  {"mmr",       {HB_TAG('H','M','N',' ')}},     /* Western Xiangxi Miao -> Hmong */
+  {"mn",        {HB_TAG('M','N','G',' ')}},     /* Mongolian [macrolanguage] */
+  {"mnc",       {HB_TAG('M','C','H',' ')}},     /* Manchu */
+  {"mni",       {HB_TAG('M','N','I',' ')}},     /* Manipuri */
+  {"mnk",       {HB_TAG('M','N','D',' '),       /* Mandinka */
+                 HB_TAG('M','N','K',' ')}},     /* Mandinka -> Maninka */
+  {"mnp",       {HB_TAG('Z','H','S',' ')}},     /* Min Bei Chinese -> Chinese Simplified */
+  {"mns",       {HB_TAG('M','A','N',' ')}},     /* Mansi */
+  {"mnw",       {HB_TAG('M','O','N',' ')}},     /* Mon */
+  {"mo",        {HB_TAG('M','O','L',' ')}},     /* Moldavian (retired code) */
+  {"moh",       {HB_TAG('M','O','H',' ')}},     /* Mohawk */
+  {"mos",       {HB_TAG('M','O','S',' ')}},     /* Mossi */
+  {"mpe",       {HB_TAG('M','A','J',' ')}},     /* Majang */
+  {"mqg",       {HB_TAG('M','L','Y',' ')}},     /* Kota Bangun Kutai Malay -> Malay */
+  {"mr",        {HB_TAG('M','A','R',' ')}},     /* Marathi */
+  {"mrh",       {HB_TAG('Q','I','N',' ')}},     /* Mara Chin -> Chin */
+  {"mrj",       {HB_TAG('H','M','A',' ')}},     /* Western Mari -> High Mari */
+  {"ms",        {HB_TAG('M','L','Y',' ')}},     /* Malay [macrolanguage] */
+  {"msc",       {HB_TAG('M','N','K',' ')}},     /* Sankaran Maninka -> Maninka */
+  {"msh",       {HB_TAG('M','L','G',' ')}},     /* Masikoro Malagasy -> Malagasy */
+  {"msi",       {HB_TAG('M','L','Y',' ')}},     /* Sabah Malay -> Malay */
+  {"mt",        {HB_TAG('M','T','S',' ')}},     /* Maltese */
+  {"mtr",       {HB_TAG('M','A','W',' ')}},     /* Mewari -> Marwari */
+  {"mui",       {HB_TAG('M','L','Y',' ')}},     /* Musi -> Malay */
+  {"mup",       {HB_TAG('R','A','J',' ')}},     /* Malvi -> Rajasthani */
+  {"muq",       {HB_TAG('H','M','N',' ')}},     /* Eastern Xiangxi Miao -> Hmong */
+  {"mus",       {HB_TAG('M','U','S',' ')}},     /* Creek -> Muscogee */
+  {"mvb",       {HB_TAG('A','T','H',' ')}},     /* Mattole -> Athapaskan */
+  {"mve",       {HB_TAG('M','A','W',' ')}},     /* Marwari (Pakistan) */
+  {"mvf",       {HB_TAG('M','N','G',' ')}},     /* Peripheral Mongolian -> Mongolian */
+  {"mwk",       {HB_TAG('M','N','K',' ')}},     /* Kita Maninkakan -> Maninka */
+  {"mwl",       {HB_TAG('M','W','L',' ')}},     /* Mirandese */
+  {"mwr",       {HB_TAG('M','A','W',' ')}},     /* Marwari [macrolanguage] */
+  {"mww",       {HB_TAG('M','W','W',' ')}},     /* Hmong Daw */
+  {"my",        {HB_TAG('B','R','M',' ')}},     /* Burmese */
+  {"mym",       {HB_TAG('M','E','N',' ')}},     /* Me'en */
+  {"myn",       {HB_TAG('M','Y','N',' ')}},     /* Mayan [family] */
+  {"myq",       {HB_TAG('M','N','K',' ')}},     /* Forest Maninka (retired code) -> Maninka */
+  {"myv",       {HB_TAG('E','R','Z',' ')}},     /* Erzya */
+  {"mzn",       {HB_TAG('M','Z','N',' ')}},     /* Mazanderani */
+  {"na",        {HB_TAG('N','A','U',' ')}},     /* Nauru -> Nauruan */
+  {"nag",       {HB_TAG('N','A','G',' ')}},     /* Naga Pidgin -> Naga-Assamese */
+  {"nah",       {HB_TAG('N','A','H',' ')}},     /* Nahuatl [family] */
+  {"nan",       {HB_TAG('Z','H','S',' ')}},     /* Min Nan Chinese -> Chinese Simplified */
+  {"nap",       {HB_TAG('N','A','P',' ')}},     /* Neapolitan */
+  {"nb",        {HB_TAG('N','O','R',' ')}},     /* Norwegian Bokmål -> Norwegian */
+  {"nd",        {HB_TAG('N','D','B',' ')}},     /* North Ndebele -> Ndebele */
+  {"ndc",       {HB_TAG('N','D','C',' ')}},     /* Ndau */
+  {"nds",       {HB_TAG('N','D','S',' ')}},     /* Low Saxon */
+  {"ne",        {HB_TAG('N','E','P',' ')}},     /* Nepali [macrolanguage] */
+  {"new",       {HB_TAG('N','E','W',' ')}},     /* Newari */
+  {"ng",        {HB_TAG('N','D','G',' ')}},     /* Ndonga */
+  {"nga",       {HB_TAG('N','G','A',' ')}},     /* Ngbaka */
+  {"ngl",       {HB_TAG('L','M','W',' ')}},     /* Lomwe */
+  {"ngo",       {HB_TAG('S','X','T',' ')}},     /* Ngoni -> Sutu */
+  {"nhd",       {HB_TAG('G','U','A',' ')}},     /* Chiripá -> Guarani */
+  {"niq",       {HB_TAG('K','A','L',' ')}},     /* Nandi -> Kalenjin */
+  {"niu",       {HB_TAG('N','I','U',' ')}},     /* Niuean */
+  {"niv",       {HB_TAG('G','I','L',' ')}},     /* Gilyak */
+  {"njz",       {HB_TAG('N','I','S',' ')}},     /* Nyishi -> Nisi */
+  {"nl",        {HB_TAG('N','L','D',' ')}},     /* Dutch */
+  {"nle",       {HB_TAG('L','U','H',' ')}},     /* East Nyala -> Luyia */
+  {"nn",        {HB_TAG('N','Y','N',' ')}},     /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+  {"no",        {HB_TAG('N','O','R',' ')}},     /* Norwegian [macrolanguage] */
+  {"nod",       {HB_TAG('N','T','A',' ')}},     /* Northern Thai -> Northern Tai */
+  {"noe",       {HB_TAG('N','O','E',' ')}},     /* Nimadi */
+  {"nog",       {HB_TAG('N','O','G',' ')}},     /* Nogai */
+  {"nov",       {HB_TAG('N','O','V',' ')}},     /* Novial */
+  {"npi",       {HB_TAG('N','E','P',' ')}},     /* Nepali */
+  {"nqo",       {HB_TAG('N','K','O',' ')}},     /* N'Ko */
+  {"nr",        {HB_TAG('N','D','B',' ')}},     /* South Ndebele -> Ndebele */
+  {"nsk",       {HB_TAG('N','A','S',' ')}},     /* Naskapi */
+  {"nso",       {HB_TAG('N','S','O',' ')}},     /* Pedi -> Sotho, Northern */
+  {"nv",        {HB_TAG('N','A','V',' '),       /* Navajo */
+                 HB_TAG('A','T','H',' ')}},     /* Navajo -> Athapaskan */
+  {"ny",        {HB_TAG('C','H','I',' ')}},     /* Chichewa (Chewa, Nyanja) */
+  {"nyd",       {HB_TAG('L','U','H',' ')}},     /* Nyore -> Luyia */
+  {"nym",       {HB_TAG('N','Y','M',' ')}},     /* Nyamwezi */
+  {"nyn",       {HB_TAG('N','K','L',' ')}},     /* Nyankole */
+  {"nza",       {HB_TAG('N','Z','A',' ')}},     /* Tigon Mbembe -> Mbembe Tigon */
+  {"oc",        {HB_TAG('O','C','I',' ')}},     /* Occitan (post 1500) */
+  {"oj",        {HB_TAG('O','J','B',' ')}},     /* Ojibwa [macrolanguage] -> Ojibway */
+  {"ojb",       {HB_TAG('O','J','B',' ')}},     /* Northwestern Ojibwa -> Ojibway */
+  {"ojc",       {HB_TAG('O','J','B',' ')}},     /* Central Ojibwa -> Ojibway */
+  {"ojg",       {HB_TAG('O','J','B',' ')}},     /* Eastern Ojibwa -> Ojibway */
+  {"ojs",       {HB_TAG('O','C','R',' ')}},     /* Severn Ojibwa -> Oji-Cree */
+  {"ojw",       {HB_TAG('O','J','B',' ')}},     /* Western Ojibwa -> Ojibway */
+  {"oki",       {HB_TAG('K','A','L',' ')}},     /* Okiek -> Kalenjin */
+  {"okm",       {HB_TAG('K','O','H',' ')}},     /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
+  {"om",        {HB_TAG('O','R','O',' ')}},     /* Oromo [macrolanguage] */
+  {"or",        {HB_TAG('O','R','I',' ')}},     /* Odia (formerly Oriya) [macrolanguage] */
+  {"orc",       {HB_TAG('O','R','O',' ')}},     /* Orma -> Oromo */
+  {"orn",       {HB_TAG('M','L','Y',' ')}},     /* Orang Kanaq -> Malay */
+  {"ors",       {HB_TAG('M','L','Y',' ')}},     /* Orang Seletar -> Malay */
+  {"ory",       {HB_TAG('O','R','I',' ')}},     /* Odia (formerly Oriya) */
+  {"os",        {HB_TAG('O','S','S',' ')}},     /* Ossetian */
+  {"otw",       {HB_TAG('O','J','B',' ')}},     /* Ottawa -> Ojibway */
+  {"pa",        {HB_TAG('P','A','N',' ')}},     /* Punjabi */
+  {"pag",       {HB_TAG('P','A','G',' ')}},     /* Pangasinan */
+  {"pam",       {HB_TAG('P','A','M',' ')}},     /* Pampanga -> Pampangan */
+  {"pap",       {HB_TAG('P','A','P','0')}},     /* Papiamento -> Papiamentu */
+  {"pau",       {HB_TAG('P','A','U',' ')}},     /* Palauan */
+  {"pbt",       {HB_TAG('P','A','S',' ')}},     /* Southern Pashto -> Pashto */
+  {"pbu",       {HB_TAG('P','A','S',' ')}},     /* Northern Pashto -> Pashto */
+  {"pcc",       {HB_TAG('P','C','C',' ')}},     /* Bouyei */
+  {"pcd",       {HB_TAG('P','C','D',' ')}},     /* Picard */
+  {"pce",       {HB_TAG('P','L','G',' ')}},     /* Ruching Palaung -> Palaung */
+  {"pck",       {HB_TAG('Q','I','N',' ')}},     /* Paite Chin -> Chin */
+  {"pdc",       {HB_TAG('P','D','C',' ')}},     /* Pennsylvania German */
+  {"pel",       {HB_TAG('M','L','Y',' ')}},     /* Pekal -> Malay */
+  {"pes",       {HB_TAG('F','A','R',' ')}},     /* Iranian Persian -> Persian */
+  {"pga",       {HB_TAG('A','R','A',' ')}},     /* Sudanese Creole Arabic -> Arabic */
+  {"phk",       {HB_TAG('P','H','K',' ')}},     /* Phake */
+  {"pi",        {HB_TAG('P','A','L',' ')}},     /* Pali */
+  {"pih",       {HB_TAG('P','I','H',' ')}},     /* Pitcairn-Norfolk -> Norfolk */
+  {"pko",       {HB_TAG('K','A','L',' ')}},     /* Pökoot -> Kalenjin */
+  {"pl",        {HB_TAG('P','L','K',' ')}},     /* Polish */
+  {"pll",       {HB_TAG('P','L','G',' ')}},     /* Shwe Palaung -> Palaung */
+  {"plp",       {HB_TAG('P','A','P',' ')}},     /* Palpa */
+  {"plt",       {HB_TAG('M','L','G',' ')}},     /* Plateau Malagasy -> Malagasy */
+  {"pms",       {HB_TAG('P','M','S',' ')}},     /* Piemontese */
+  {"pnb",       {HB_TAG('P','N','B',' ')}},     /* Western Panjabi */
+  {"poh",       {HB_TAG('P','O','H',' ')}},     /* Poqomchi' -> Pocomchi */
+  {"pon",       {HB_TAG('P','O','N',' ')}},     /* Pohnpeian */
+  {"ppa",       {HB_TAG('B','A','G',' ')}},     /* Pao (retired code) -> Baghelkhandi */
+  {"pro",       {HB_TAG('P','R','O',' ')}},     /* Old Provençal (to 1500) -> Provençal / Old Provençal */
+  {"prs",       {HB_TAG('D','R','I',' ')}},     /* Dari */
+  {"ps",        {HB_TAG('P','A','S',' ')}},     /* Pashto [macrolanguage] */
+  {"pse",       {HB_TAG('M','L','Y',' ')}},     /* Central Malay -> Malay */
+  {"pst",       {HB_TAG('P','A','S',' ')}},     /* Central Pashto -> Pashto */
+  {"pt",        {HB_TAG('P','T','G',' ')}},     /* Portuguese */
+  {"pwo",       {HB_TAG('P','W','O',' ')}},     /* Pwo Western Karen -> Western Pwo Karen */
+  {"qu",        {HB_TAG('Q','U','Z',' ')}},     /* Quechua [macrolanguage] */
+  {"qub",       {HB_TAG('Q','W','H',' ')}},     /* Huallaga Huánuco Quechua -> Quechua (Peru) */
+  {"quc",       {HB_TAG('Q','U','C',' ')}},     /* K’iche’ */
+  {"qud",       {HB_TAG('Q','V','I',' ')}},     /* Calderón Highland Quichua -> Quechua (Ecuador) */
+  {"quf",       {HB_TAG('Q','U','Z',' ')}},     /* Lambayeque Quechua -> Quechua */
+  {"qug",       {HB_TAG('Q','V','I',' ')}},     /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
+  {"quh",       {HB_TAG('Q','U','H',' ')}},     /* South Bolivian Quechua -> Quechua (Bolivia) */
+  {"quk",       {HB_TAG('Q','U','Z',' ')}},     /* Chachapoyas Quechua -> Quechua */
+  {"qul",       {HB_TAG('Q','U','Z',' ')}},     /* North Bolivian Quechua -> Quechua */
+  {"qup",       {HB_TAG('Q','V','I',' ')}},     /* Southern Pastaza Quechua -> Quechua (Ecuador) */
+  {"qur",       {HB_TAG('Q','W','H',' ')}},     /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
+  {"qus",       {HB_TAG('Q','U','H',' ')}},     /* Santiago del Estero Quichua -> Quechua (Bolivia) */
+  {"quw",       {HB_TAG('Q','V','I',' ')}},     /* Tena Lowland Quichua -> Quechua (Ecuador) */
+  {"qux",       {HB_TAG('Q','W','H',' ')}},     /* Yauyos Quechua -> Quechua (Peru) */
+  {"quy",       {HB_TAG('Q','U','Z',' ')}},     /* Ayacucho Quechua -> Quechua */
+  {"quz",       {HB_TAG('Q','U','Z',' ')}},     /* Cusco Quechua -> Quechua */
+  {"qva",       {HB_TAG('Q','W','H',' ')}},     /* Ambo-Pasco Quechua -> Quechua (Peru) */
+  {"qvc",       {HB_TAG('Q','U','Z',' ')}},     /* Cajamarca Quechua -> Quechua */
+  {"qve",       {HB_TAG('Q','U','Z',' ')}},     /* Eastern Apurímac Quechua -> Quechua */
+  {"qvh",       {HB_TAG('Q','W','H',' ')}},     /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
+  {"qvi",       {HB_TAG('Q','V','I',' ')}},     /* Imbabura Highland Quichua -> Quechua (Ecuador) */
+  {"qvj",       {HB_TAG('Q','V','I',' ')}},     /* Loja Highland Quichua -> Quechua (Ecuador) */
+  {"qvl",       {HB_TAG('Q','W','H',' ')}},     /* Cajatambo North Lima Quechua -> Quechua (Peru) */
+  {"qvm",       {HB_TAG('Q','W','H',' ')}},     /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
+  {"qvn",       {HB_TAG('Q','W','H',' ')}},     /* North Junín Quechua -> Quechua (Peru) */
+  {"qvo",       {HB_TAG('Q','V','I',' ')}},     /* Napo Lowland Quechua -> Quechua (Ecuador) */
+  {"qvp",       {HB_TAG('Q','W','H',' ')}},     /* Pacaraos Quechua -> Quechua (Peru) */
+  {"qvs",       {HB_TAG('Q','U','Z',' ')}},     /* San Martín Quechua -> Quechua */
+  {"qvw",       {HB_TAG('Q','W','H',' ')}},     /* Huaylla Wanca Quechua -> Quechua (Peru) */
+  {"qvz",       {HB_TAG('Q','V','I',' ')}},     /* Northern Pastaza Quichua -> Quechua (Ecuador) */
+  {"qwa",       {HB_TAG('Q','W','H',' ')}},     /* Corongo Ancash Quechua -> Quechua (Peru) */
+  {"qwc",       {HB_TAG('Q','U','Z',' ')}},     /* Classical Quechua -> Quechua */
+  {"qwh",       {HB_TAG('Q','W','H',' ')}},     /* Huaylas Ancash Quechua -> Quechua (Peru) */
+  {"qws",       {HB_TAG('Q','W','H',' ')}},     /* Sihuas Ancash Quechua -> Quechua (Peru) */
+  {"qxa",       {HB_TAG('Q','W','H',' ')}},     /* Chiquián Ancash Quechua -> Quechua (Peru) */
+  {"qxc",       {HB_TAG('Q','W','H',' ')}},     /* Chincha Quechua -> Quechua (Peru) */
+  {"qxh",       {HB_TAG('Q','W','H',' ')}},     /* Panao Huánuco Quechua -> Quechua (Peru) */
+  {"qxl",       {HB_TAG('Q','V','I',' ')}},     /* Salasaca Highland Quichua -> Quechua (Ecuador) */
+  {"qxn",       {HB_TAG('Q','W','H',' ')}},     /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
+  {"qxo",       {HB_TAG('Q','W','H',' ')}},     /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
+  {"qxp",       {HB_TAG('Q','U','Z',' ')}},     /* Puno Quechua -> Quechua */
+  {"qxr",       {HB_TAG('Q','V','I',' ')}},     /* Cañar Highland Quichua -> Quechua (Ecuador) */
+  {"qxt",       {HB_TAG('Q','W','H',' ')}},     /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
+  {"qxu",       {HB_TAG('Q','U','Z',' ')}},     /* Arequipa-La Unión Quechua -> Quechua */
+  {"qxw",       {HB_TAG('Q','W','H',' ')}},     /* Jauja Wanca Quechua -> Quechua (Peru) */
+  {"rag",       {HB_TAG('L','U','H',' ')}},     /* Logooli -> Luyia */
+  {"raj",       {HB_TAG('R','A','J',' ')}},     /* Rajasthani [macrolanguage] */
+  {"rar",       {HB_TAG('R','A','R',' ')}},     /* Rarotongan */
+  {"rbb",       {HB_TAG('P','L','G',' ')}},     /* Rumai Palaung -> Palaung */
+  {"rbl",       {HB_TAG('B','I','K',' ')}},     /* Miraya Bikol -> Bikol */
+  {"rej",       {HB_TAG('R','E','J',' ')}},     /* Rejang */
+  {"ria",       {HB_TAG('R','I','A',' ')}},     /* Riang (India) */
+  {"rif",       {HB_TAG('R','I','F',' ')}},     /* Tarifit */
+  {"rit",       {HB_TAG('R','I','T',' ')}},     /* Ritarungo */
+  {"rki",       {HB_TAG('A','R','K',' ')}},     /* Rakhine */
+  {"rkw",       {HB_TAG('R','K','W',' ')}},     /* Arakwal */
+  {"rm",        {HB_TAG('R','M','S',' ')}},     /* Romansh */
+  {"rmc",       {HB_TAG('R','O','Y',' ')}},     /* Carpathian Romani -> Romany */
+  {"rmf",       {HB_TAG('R','O','Y',' ')}},     /* Kalo Finnish Romani -> Romany */
+  {"rml",       {HB_TAG('R','O','Y',' ')}},     /* Baltic Romani -> Romany */
+  {"rmn",       {HB_TAG('R','O','Y',' ')}},     /* Balkan Romani -> Romany */
+  {"rmo",       {HB_TAG('R','O','Y',' ')}},     /* Sinte Romani -> Romany */
+  {"rmw",       {HB_TAG('R','O','Y',' ')}},     /* Welsh Romani -> Romany */
+  {"rmy",       {HB_TAG('R','M','Y',' ')}},     /* Vlax Romani */
+  {"rmz",       {HB_TAG('A','R','K',' ')}},     /* Marma -> Rakhine */
+  {"rn",        {HB_TAG('R','U','N',' ')}},     /* Rundi */
+  {"rnl",       {HB_TAG('H','A','L',' ')}},     /* Ranglong -> Halam (Falam Chin) */
+  {"ro",        {HB_TAG('R','O','M',' ')}},     /* Romanian */
+  {"rom",       {HB_TAG('R','O','Y',' ')}},     /* Romany [macrolanguage] */
+  {"rtm",       {HB_TAG('R','T','M',' ')}},     /* Rotuman */
+  {"ru",        {HB_TAG('R','U','S',' ')}},     /* Russian */
+  {"rue",       {HB_TAG('R','S','Y',' ')}},     /* Rusyn */
+  {"rup",       {HB_TAG('R','U','P',' ')}},     /* Aromanian */
+  {"rw",        {HB_TAG('R','U','A',' ')}},     /* Kinyarwanda */
+  {"rwr",       {HB_TAG('M','A','W',' ')}},     /* Marwari (India) */
+  {"sa",        {HB_TAG('S','A','N',' ')}},     /* Sanskrit */
+  {"sah",       {HB_TAG('Y','A','K',' ')}},     /* Yakut -> Sakha */
+  {"sam",       {HB_TAG('P','A','A',' ')}},     /* Samaritan Aramaic -> Palestinian Aramaic */
+  {"sas",       {HB_TAG('S','A','S',' ')}},     /* Sasak */
+  {"sat",       {HB_TAG('S','A','T',' ')}},     /* Santali */
+  {"sc",        {HB_TAG('S','R','D',' ')}},     /* Sardinian [macrolanguage] */
+  {"sck",       {HB_TAG('S','A','D',' ')}},     /* Sadri */
+  {"scn",       {HB_TAG('S','C','N',' ')}},     /* Sicilian */
+  {"sco",       {HB_TAG('S','C','O',' ')}},     /* Scots */
+  {"scs",       {HB_TAG('S','C','S',' '),       /* North Slavey */
+                 HB_TAG('S','L','A',' '),       /* North Slavey -> Slavey */
+                 HB_TAG('A','T','H',' ')}},     /* North Slavey -> Athapaskan */
+  {"sd",        {HB_TAG('S','N','D',' ')}},     /* Sindhi */
+  {"sdc",       {HB_TAG('S','R','D',' ')}},     /* Sassarese Sardinian -> Sardinian */
+  {"sdh",       {HB_TAG('K','U','R',' ')}},     /* Southern Kurdish -> Kurdish */
+  {"sdn",       {HB_TAG('S','R','D',' ')}},     /* Gallurese Sardinian -> Sardinian */
+  {"se",        {HB_TAG('N','S','M',' ')}},     /* Northern Sami */
+  {"seh",       {HB_TAG('S','N','A',' ')}},     /* Sena */
+  {"sek",       {HB_TAG('A','T','H',' ')}},     /* Sekani -> Athapaskan */
+  {"sel",       {HB_TAG('S','E','L',' ')}},     /* Selkup */
+  {"sez",       {HB_TAG('Q','I','N',' ')}},     /* Senthang Chin -> Chin */
+  {"sfm",       {HB_TAG('H','M','N',' ')}},     /* Small Flowery Miao -> Hmong */
+  {"sg",        {HB_TAG('S','G','O',' ')}},     /* Sango */
+  {"sga",       {HB_TAG('S','G','A',' ')}},     /* Old Irish (to 900) */
+  {"sgc",       {HB_TAG('K','A','L',' ')}},     /* Kipsigis -> Kalenjin */
+  {"sgs",       {HB_TAG('S','G','S',' ')}},     /* Samogitian */
+  {"sgw",       {HB_TAG('C','H','G',' '),       /* Sebat Bet Gurage -> Chaha Gurage */
+                 HB_TAG('S','G','W',' ')}},     /* Sebat Bet Gurage -> Chaha Gurage (SIL fonts) */
+  {"shi",       {HB_TAG('S','H','I',' ')}},     /* Tachelhit */
+  {"shn",       {HB_TAG('S','H','N',' ')}},     /* Shan */
+  {"shu",       {HB_TAG('A','R','A',' ')}},     /* Chadian Arabic -> Arabic */
+  {"si",        {HB_TAG('S','N','H',' ')}},     /* Sinhala (Sinhalese) */
+  {"sid",       {HB_TAG('S','I','D',' ')}},     /* Sidamo */
+  {"sjd",       {HB_TAG('K','S','M',' ')}},     /* Kildin Sami */
+  {"sjo",       {HB_TAG('S','I','B',' ')}},     /* Xibe -> Sibe */
+  {"sk",        {HB_TAG('S','K','Y',' ')}},     /* Slovak */
+  {"skg",       {HB_TAG('M','L','G',' ')}},     /* Sakalava Malagasy -> Malagasy */
+  {"skr",       {HB_TAG('S','R','K',' ')}},     /* Saraiki */
+  {"sl",        {HB_TAG('S','L','V',' ')}},     /* Slovenian */
+  {"sm",        {HB_TAG('S','M','O',' ')}},     /* Samoan */
+  {"sma",       {HB_TAG('S','S','M',' ')}},     /* Southern Sami */
+  {"smj",       {HB_TAG('L','S','M',' ')}},     /* Lule Sami */
+  {"smn",       {HB_TAG('I','S','M',' ')}},     /* Inari Sami */
+  {"sms",       {HB_TAG('S','K','S',' ')}},     /* Skolt Sami */
+  {"sn",        {HB_TAG('S','N','A','0')}},     /* Shona */
+  {"snk",       {HB_TAG('S','N','K',' ')}},     /* Soninke */
+  {"so",        {HB_TAG('S','M','L',' ')}},     /* Somali */
+  {"sop",       {HB_TAG('S','O','P',' ')}},     /* Songe */
+  {"spv",       {HB_TAG('O','R','I',' ')}},     /* Sambalpuri -> Odia (formerly Oriya) */
+  {"spy",       {HB_TAG('K','A','L',' ')}},     /* Sabaot -> Kalenjin */
+  {"sq",        {HB_TAG('S','Q','I',' ')}},     /* Albanian [macrolanguage] */
+  {"sr",        {HB_TAG('S','R','B',' ')}},     /* Serbian */
+  {"src",       {HB_TAG('S','R','D',' ')}},     /* Logudorese Sardinian -> Sardinian */
+  {"sro",       {HB_TAG('S','R','D',' ')}},     /* Campidanese Sardinian -> Sardinian */
+  {"srr",       {HB_TAG('S','R','R',' ')}},     /* Serer */
+  {"srs",       {HB_TAG('A','T','H',' ')}},     /* Sarsi -> Athapaskan */
+  {"ss",        {HB_TAG('S','W','Z',' ')}},     /* Swati */
+  {"ssh",       {HB_TAG('A','R','A',' ')}},     /* Shihhi Arabic -> Arabic */
+  {"st",        {HB_TAG('S','O','T',' ')}},     /* Southern Sotho -> Sotho, Southern */
+  {"stq",       {HB_TAG('S','T','Q',' ')}},     /* Saterfriesisch -> Saterland Frisian */
+  {"stv",       {HB_TAG('S','I','G',' ')}},     /* Silt'e -> Silte Gurage */
+  {"su",        {HB_TAG('S','U','N',' ')}},     /* Sundanese */
+  {"suk",       {HB_TAG('S','U','K',' ')}},     /* Sukuma */
+  {"suq",       {HB_TAG('S','U','R',' ')}},     /* Suri */
+  {"sv",        {HB_TAG('S','V','E',' ')}},     /* Swedish */
+  {"sva",       {HB_TAG('S','V','A',' ')}},     /* Svan */
+  {"sw",        {HB_TAG('S','W','K',' ')}},     /* Swahili [macrolanguage] */
+  {"swb",       {HB_TAG('C','M','R',' ')}},     /* Maore Comorian -> Comorian */
+  {"swc",       {HB_TAG('S','W','K',' ')}},     /* Congo Swahili -> Swahili */
+  {"swh",       {HB_TAG('S','W','K',' ')}},     /* Swahili */
+  {"swv",       {HB_TAG('M','A','W',' ')}},     /* Shekhawati -> Marwari */
+  {"sxu",       {HB_TAG('S','X','U',' ')}},     /* Upper Saxon */
+  {"syc",       {HB_TAG('S','Y','R',' ')}},     /* Classical Syriac -> Syriac */
+  {"syl",       {HB_TAG('S','Y','L',' ')}},     /* Sylheti */
+  {"syr",       {HB_TAG('S','Y','R',' ')}},     /* Syriac [macrolanguage] */
+  {"szl",       {HB_TAG('S','Z','L',' ')}},     /* Silesian */
+  {"ta",        {HB_TAG('T','A','M',' ')}},     /* Tamil */
+  {"taa",       {HB_TAG('A','T','H',' ')}},     /* Lower Tanana -> Athapaskan */
+  {"tab",       {HB_TAG('T','A','B',' ')}},     /* Tabassaran -> Tabasaran */
+  {"taq",       {HB_TAG('T','M','H',' ')}},     /* Tamasheq -> Tamashek */
+  {"tau",       {HB_TAG('A','T','H',' ')}},     /* Upper Tanana -> Athapaskan */
+  {"tcb",       {HB_TAG('A','T','H',' ')}},     /* Tanacross -> Athapaskan */
+  {"tce",       {HB_TAG('A','T','H',' ')}},     /* Southern Tutchone -> Athapaskan */
+  {"tcp",       {HB_TAG('Q','I','N',' ')}},     /* Tawr Chin -> Chin */
+  {"tcy",       {HB_TAG('T','U','L',' ')}},     /* Tulu -> Tumbuka */
+  {"tcz",       {HB_TAG('Q','I','N',' ')}},     /* Thado Chin -> Chin */
+  {"tdd",       {HB_TAG('T','D','D',' ')}},     /* Tai Nüa -> Dehong Dai */
+  {"tdx",       {HB_TAG('M','L','G',' ')}},     /* Tandroy-Mahafaly Malagasy -> Malagasy */
+  {"te",        {HB_TAG('T','E','L',' ')}},     /* Telugu */
+  {"tec",       {HB_TAG('K','A','L',' ')}},     /* Terik -> Kalenjin */
+  {"tem",       {HB_TAG('T','M','N',' ')}},     /* Timne -> Temne */
+  {"tet",       {HB_TAG('T','E','T',' ')}},     /* Tetum */
+  {"tfn",       {HB_TAG('A','T','H',' ')}},     /* Tanaina -> Athapaskan */
+  {"tg",        {HB_TAG('T','A','J',' ')}},     /* Tajik -> Tajiki */
+  {"tgj",       {HB_TAG('N','I','S',' ')}},     /* Tagin -> Nisi */
+  {"tgx",       {HB_TAG('A','T','H',' ')}},     /* Tagish -> Athapaskan */
+  {"th",        {HB_TAG('T','H','A',' ')}},     /* Thai */
+  {"tht",       {HB_TAG('A','T','H',' ')}},     /* Tahltan -> Athapaskan */
+  {"thv",       {HB_TAG('T','M','H',' ')}},     /* Tahaggart Tamahaq -> Tamashek */
+  {"thz",       {HB_TAG('T','M','H',' ')}},     /* Tayart Tamajeq -> Tamashek */
+  {"ti",        {HB_TAG('T','G','Y',' ')}},     /* Tigrinya */
+  {"tig",       {HB_TAG('T','G','R',' ')}},     /* Tigre */
+  {"tiv",       {HB_TAG('T','I','V',' ')}},     /* Tiv */
+  {"tk",        {HB_TAG('T','K','M',' ')}},     /* Turkmen */
+  {"tkg",       {HB_TAG('M','L','G',' ')}},     /* Tesaka Malagasy -> Malagasy */
+  {"tl",        {HB_TAG('T','G','L',' ')}},     /* Tagalog */
+  {"tmh",       {HB_TAG('T','M','H',' ')}},     /* Tamashek [macrolanguage] */
+  {"tmw",       {HB_TAG('M','L','Y',' ')}},     /* Temuan -> Malay */
+  {"tn",        {HB_TAG('T','N','A',' ')}},     /* Tswana */
+  {"tnf",       {HB_TAG('D','R','I',' ')}},     /* Tangshewi (retired code) -> Dari */
+  {"to",        {HB_TAG('T','G','N',' ')}},     /* Tonga (Tonga Islands) -> Tongan */
+  {"tod",       {HB_TAG('T','O','D','0')}},     /* Toma */
+  {"toi",       {HB_TAG('T','N','G',' ')}},     /* Tonga (Zambia) */
+  {"tol",       {HB_TAG('A','T','H',' ')}},     /* Tolowa -> Athapaskan */
+  {"tpi",       {HB_TAG('T','P','I',' ')}},     /* Tok Pisin */
+  {"tr",        {HB_TAG('T','R','K',' ')}},     /* Turkish */
+  {"tru",       {HB_TAG('T','U','A',' '),       /* Turoyo -> Turoyo Aramaic */
+                 HB_TAG('S','Y','R',' ')}},     /* Turoyo -> Syriac */
+  {"ts",        {HB_TAG('T','S','G',' ')}},     /* Tsonga */
+  {"tsj",       {HB_TAG('T','S','J',' ')}},     /* Tshangla */
+  {"tt",        {HB_TAG('T','A','T',' ')}},     /* Tatar */
+  {"ttm",       {HB_TAG('A','T','H',' ')}},     /* Northern Tutchone -> Athapaskan */
+  {"ttq",       {HB_TAG('T','M','H',' ')}},     /* Tawallammat Tamajaq -> Tamashek */
+  {"tum",       {HB_TAG('T','U','M',' ')}},     /* Tumbuka -> Tulu */
+  {"tuu",       {HB_TAG('A','T','H',' ')}},     /* Tututni -> Athapaskan */
+  {"tuy",       {HB_TAG('K','A','L',' ')}},     /* Tugen -> Kalenjin */
+  {"tvl",       {HB_TAG('T','V','L',' ')}},     /* Tuvalu */
+  {"tw",        {HB_TAG('T','W','I',' '),       /* Twi */
+                 HB_TAG('A','K','A',' ')}},     /* Twi -> Akan */
+  {"txc",       {HB_TAG('A','T','H',' ')}},     /* Tsetsaut -> Athapaskan */
+  {"txy",       {HB_TAG('M','L','G',' ')}},     /* Tanosy Malagasy -> Malagasy */
+  {"ty",        {HB_TAG('T','H','T',' ')}},     /* Tahitian */
+  {"tyv",       {HB_TAG('T','U','V',' ')}},     /* Tuvinian -> Tuvin */
+  {"tyz",       {HB_TAG('T','Y','Z',' ')}},     /* Tày */
+  {"tzm",       {HB_TAG('T','Z','M',' ')}},     /* Central Atlas Tamazight -> Tamazight */
+  {"tzo",       {HB_TAG('T','Z','O',' ')}},     /* Tzotzil */
+  {"ubl",       {HB_TAG('B','I','K',' ')}},     /* Buhi'non Bikol -> Bikol */
+  {"udm",       {HB_TAG('U','D','M',' ')}},     /* Udmurt */
+  {"ug",        {HB_TAG('U','Y','G',' ')}},     /* Uyghur */
+  {"uk",        {HB_TAG('U','K','R',' ')}},     /* Ukrainian */
+  {"umb",       {HB_TAG('U','M','B',' ')}},     /* Umbundu */
+  {"unr",       {HB_TAG('M','U','N',' ')}},     /* Mundari */
+  {"ur",        {HB_TAG('U','R','D',' ')}},     /* Urdu */
+  {"urk",       {HB_TAG('M','L','Y',' ')}},     /* Urak Lawoi' -> Malay */
+  {"uz",        {HB_TAG('U','Z','B',' ')}},     /* Uzbek [macrolanguage] */
+  {"uzn",       {HB_TAG('U','Z','B',' ')}},     /* Northern Uzbek -> Uzbek */
+  {"uzs",       {HB_TAG('U','Z','B',' ')}},     /* Southern Uzbek -> Uzbek */
+  {"ve",        {HB_TAG('V','E','N',' ')}},     /* Venda */
+  {"vec",       {HB_TAG('V','E','C',' ')}},     /* Venetian */
+  {"vi",        {HB_TAG('V','I','T',' ')}},     /* Vietnamese */
+  {"vkk",       {HB_TAG('M','L','Y',' ')}},     /* Kaur -> Malay */
+  {"vkt",       {HB_TAG('M','L','Y',' ')}},     /* Tenggarong Kutai Malay -> Malay */
+  {"vls",       {HB_TAG('F','L','E',' ')}},     /* Vlaams -> Dutch (Flemish) */
+  {"vmw",       {HB_TAG('M','A','K',' ')}},     /* Makhuwa */
+  {"vo",        {HB_TAG('V','O','L',' ')}},     /* Volapük */
+  {"vro",       {HB_TAG('V','R','O',' ')}},     /* Võro */
+  {"wa",        {HB_TAG('W','L','N',' ')}},     /* Walloon */
+  {"war",       {HB_TAG('W','A','R',' ')}},     /* Waray (Philippines) -> Waray-Waray */
+  {"wbm",       {HB_TAG('W','A',' ',' ')}},     /* Wa */
+  {"wbr",       {HB_TAG('W','A','G',' ')}},     /* Wagdi */
+  {"wlc",       {HB_TAG('C','M','R',' ')}},     /* Mwali Comorian -> Comorian */
+  {"wle",       {HB_TAG('S','I','G',' ')}},     /* Wolane -> Silte Gurage */
+  {"wlk",       {HB_TAG('A','T','H',' ')}},     /* Wailaki -> Athapaskan */
+  {"wni",       {HB_TAG('C','M','R',' ')}},     /* Ndzwani Comorian -> Comorian */
+  {"wo",        {HB_TAG('W','L','F',' ')}},     /* Wolof */
+  {"wry",       {HB_TAG('M','A','W',' ')}},     /* Merwari -> Marwari */
+  {"wsg",       {HB_TAG('G','O','N',' ')}},     /* Adilabad Gondi -> Gondi */
+  {"wtm",       {HB_TAG('W','T','M',' ')}},     /* Mewati */
+  {"wuu",       {HB_TAG('Z','H','S',' ')}},     /* Wu Chinese -> Chinese Simplified */
+  {"xal",       {HB_TAG('K','L','M',' '),       /* Kalmyk */
+                 HB_TAG('T','O','D',' ')}},     /* Kalmyk -> Todo */
+  {"xan",       {HB_TAG('S','E','K',' ')}},     /* Xamtanga -> Sekota */
+  {"xh",        {HB_TAG('X','H','S',' ')}},     /* Xhosa */
+  {"xjb",       {HB_TAG('X','J','B',' ')}},     /* Minjungbal -> Minjangbal */
+  {"xkf",       {HB_TAG('X','K','F',' ')}},     /* Khengkha */
+  {"xmm",       {HB_TAG('M','L','Y',' ')}},     /* Manado Malay -> Malay */
+  {"xmv",       {HB_TAG('M','L','G',' ')}},     /* Antankarana Malagasy -> Malagasy */
+  {"xmw",       {HB_TAG('M','L','G',' ')}},     /* Tsimihety Malagasy -> Malagasy */
+  {"xnr",       {HB_TAG('D','G','R',' ')}},     /* Kangri -> Dogri */
+  {"xog",       {HB_TAG('X','O','G',' ')}},     /* Soga */
+  {"xpe",       {HB_TAG('X','P','E',' ')}},     /* Liberia Kpelle -> Kpelle (Liberia) */
+  {"xsl",       {HB_TAG('S','S','L',' '),       /* South Slavey */
+                 HB_TAG('S','L','A',' '),       /* South Slavey -> Slavey */
+                 HB_TAG('A','T','H',' ')}},     /* South Slavey -> Athapaskan */
+  {"xst",       {HB_TAG('S','I','G',' ')}},     /* Silt'e (retired code) -> Silte Gurage */
+  {"xwo",       {HB_TAG('T','O','D',' ')}},     /* Written Oirat -> Todo */
+  {"yao",       {HB_TAG('Y','A','O',' ')}},     /* Yao */
+  {"yap",       {HB_TAG('Y','A','P',' ')}},     /* Yapese */
+  {"ybd",       {HB_TAG('A','R','K',' ')}},     /* Yangbye (retired code) -> Rakhine */
+  {"ydd",       {HB_TAG('J','I','I',' ')}},     /* Eastern Yiddish -> Yiddish */
+  {"yi",        {HB_TAG('J','I','I',' ')}},     /* Yiddish [macrolanguage] */
+  {"yih",       {HB_TAG('J','I','I',' ')}},     /* Western Yiddish -> Yiddish */
+  {"yo",        {HB_TAG('Y','B','A',' ')}},     /* Yoruba */
+  {"yos",       {HB_TAG('Q','I','N',' ')}},     /* Yos (retired code) -> Chin */
+  {"yrk",       {HB_TAG('T','N','E',' '),       /* Nenets -> Tundra Nenets */
+                 HB_TAG('F','N','E',' ')}},     /* Nenets -> Forest Nenets */
+  {"yue",       {HB_TAG('Z','H','H',' ')}},     /* Yue Chinese -> Chinese, Hong Kong SAR */
+  {"za",        {HB_TAG('Z','H','A',' ')}},     /* Zhuang [macrolanguage] */
+  {"zch",       {HB_TAG('Z','H','A',' ')}},     /* Central Hongshuihe Zhuang -> Zhuang */
+  {"zdj",       {HB_TAG('C','M','R',' ')}},     /* Ngazidja Comorian -> Comorian */
+  {"zea",       {HB_TAG('Z','E','A',' ')}},     /* Zeeuws -> Zealandic */
+  {"zeh",       {HB_TAG('Z','H','A',' ')}},     /* Eastern Hongshuihe Zhuang -> Zhuang */
+  {"zgb",       {HB_TAG('Z','H','A',' ')}},     /* Guibei Zhuang -> Zhuang */
+  {"zgh",       {HB_TAG('Z','G','H',' ')}},     /* Standard Moroccan Tamazight */
+  {"zgm",       {HB_TAG('Z','H','A',' ')}},     /* Minz Zhuang -> Zhuang */
+  {"zgn",       {HB_TAG('Z','H','A',' ')}},     /* Guibian Zhuang -> Zhuang */
+  {"zh",        {HB_TAG('Z','H','S',' ')}},     /* Chinese [macrolanguage] -> Chinese Simplified */
+  {"zhd",       {HB_TAG('Z','H','A',' ')}},     /* Dai Zhuang -> Zhuang */
+  {"zhn",       {HB_TAG('Z','H','A',' ')}},     /* Nong Zhuang -> Zhuang */
+  {"zlj",       {HB_TAG('Z','H','A',' ')}},     /* Liujiang Zhuang -> Zhuang */
+  {"zlm",       {HB_TAG('M','L','Y',' ')}},     /* Malay */
+  {"zln",       {HB_TAG('Z','H','A',' ')}},     /* Lianshan Zhuang -> Zhuang */
+  {"zlq",       {HB_TAG('Z','H','A',' ')}},     /* Liuqian Zhuang -> Zhuang */
+  {"zmi",       {HB_TAG('M','L','Y',' ')}},     /* Negeri Sembilan Malay -> Malay */
+  {"zne",       {HB_TAG('Z','N','D',' ')}},     /* Zande */
+  {"zom",       {HB_TAG('Q','I','N',' ')}},     /* Zou -> Chin */
+  {"zqe",       {HB_TAG('Z','H','A',' ')}},     /* Qiubei Zhuang -> Zhuang */
+  {"zsm",       {HB_TAG('M','L','Y',' ')}},     /* Standard Malay -> Malay */
+  {"zu",        {HB_TAG('Z','U','L',' ')}},     /* Zulu */
+  {"zum",       {HB_TAG('L','R','C',' ')}},     /* Kumzari -> Luri */
+  {"zyb",       {HB_TAG('Z','H','A',' ')}},     /* Yongbei Zhuang -> Zhuang */
+  {"zyg",       {HB_TAG('Z','H','A',' ')}},     /* Yang Zhuang -> Zhuang */
+  {"zyj",       {HB_TAG('Z','H','A',' ')}},     /* Youjiang Zhuang -> Zhuang */
+  {"zyn",       {HB_TAG('Z','H','A',' ')}},     /* Yongnan Zhuang -> Zhuang */
+  {"zza",       {HB_TAG('Z','Z','A',' ')}},     /* Zazaki [macrolanguage] */
+  {"zzj",       {HB_TAG('Z','H','A',' ')}},     /* Zuojiang Zhuang -> Zhuang */
+};
+
+static_assert (HB_OT_MAX_TAGS_PER_LANGUAGE == 3u, "");
+
+/**
+ * hb_ot_tags_from_complex_language:
+ * @lang_str: a BCP 47 language tag to convert.
+ * @limit: a pointer to the end of the substring of @lang_str to consider for
+ * conversion.
+ * @count: maximum number of language tags to retrieve (IN) and actual number of
+ * language tags retrieved (OUT). If no tags are retrieved, it is not modified.
+ * @tags: array of size at least @language_count to store the language tag
+ * results
+ *
+ * Converts a multi-subtag BCP 47 language tag to language tags.
+ *
+ * Return value: Whether any language systems were retrieved.
+ **/
+static bool
+hb_ot_tags_from_complex_language (const char   *lang_str,
+                                  const char   *limit,
+                                  unsigned int *count /* IN/OUT */,
+                                  hb_tag_t     *tags /* OUT */)
+{
+  if (subtag_matches (lang_str, limit, "-fonnapa"))
+  {
+    /* Undetermined; North American Phonetic Alphabet */
+    tags[0] = HB_TAG('A','P','P','H');  /* Phonetic transcription—Americanist conventions */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-polyton"))
+  {
+    /* Modern Greek (1453-); Polytonic Greek */
+    tags[0] = HB_TAG('P','G','R',' ');  /* Polytonic Greek */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-provenc"))
+  {
+    /* Occitan (post 1500); Provençal */
+    tags[0] = HB_TAG('P','R','O',' ');  /* Provençal / Old Provençal */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-fonipa"))
+  {
+    /* Undetermined; International Phonetic Alphabet */
+    tags[0] = HB_TAG('I','P','P','H');  /* Phonetic transcription—IPA conventions */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-geok"))
+  {
+    /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+    tags[0] = HB_TAG('K','G','E',' ');  /* Khutsuri Georgian */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syre"))
+  {
+    /* Undetermined; Syriac (Estrangelo variant) */
+    tags[0] = HB_TAG('S','Y','R','E');  /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syrj"))
+  {
+    /* Undetermined; Syriac (Western variant) */
+    tags[0] = HB_TAG('S','Y','R','J');  /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+    *count = 1;
+    return true;
+  }
+  if (subtag_matches (lang_str, limit, "-syrn"))
+  {
+    /* Undetermined; Syriac (Eastern variant) */
+    tags[0] = HB_TAG('S','Y','R','N');  /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+    *count = 1;
+    return true;
+  }
+  switch (lang_str[0])
+  {
+  case 'a':
+    if (0 == strcmp (&lang_str[1], "rt-lojban"))
+    {
+      /* Lojban */
+      tags[0] = HB_TAG('J','B','O',' ');  /* Lojban */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'c':
+    if (lang_matches (&lang_str[1], "do-hant-hk"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hant-mo"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant-hk"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant-mo"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant-hk"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant-mo"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant-hk"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant-mo"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant-hk"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant-mo"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant-hk"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant-mo"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hans"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "do-hant"))
+    {
+      /* Min Dong Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hans"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "jy-hant"))
+    {
+      /* Jinyu Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hans"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "mn-hant"))
+    {
+      /* Mandarin Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hans"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "px-hant"))
+    {
+      /* Pu-Xian Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hans"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zh-hant"))
+    {
+      /* Huizhou Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hans"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "zo-hant"))
+    {
+      /* Min Zhong Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Dong Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Dong Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "do-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Dong Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Jinyu Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Jinyu Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "jy-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Jinyu Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Mandarin Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Mandarin Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "mn-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Mandarin Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Pu-Xian Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Pu-Xian Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "px-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Pu-Xian Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Huizhou Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Huizhou Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zh-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Huizhou Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Zhong Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Zhong Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "zo-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Zhong Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'g':
+    if (lang_matches (&lang_str[1], "an-hant-hk"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant-mo"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hans"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant"))
+    {
+      /* Gan Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "a-latg"))
+    {
+      /* Irish */
+      tags[0] = HB_TAG('I','R','T',' ');  /* Irish Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Gan Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Gan Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Gan Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'h':
+    if (lang_matches (&lang_str[1], "ak-hant-hk"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hant-mo"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant-hk"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant-mo"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hans"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "ak-hant"))
+    {
+      /* Hakka Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hans"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "sn-hant"))
+    {
+      /* Xiang Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Hakka Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Hakka Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "ak-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Hakka Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Xiang Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Xiang Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "sn-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Xiang Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'i':
+    if (0 == strcmp (&lang_str[1], "-navajo"))
+    {
+      /* Navajo */
+      unsigned int i;
+      hb_tag_t possible_tags[] = {
+        HB_TAG('N','A','V',' '),  /* Navajo */
+        HB_TAG('A','T','H',' '),  /* Athapaskan */
+      };
+      for (i = 0; i < 2 && i < *count; i++)
+        tags[i] = possible_tags[i];
+      *count = i;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "-hak"))
+    {
+      /* Hakka */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "-lux"))
+    {
+      /* Luxembourgish */
+      tags[0] = HB_TAG('L','T','Z',' ');  /* Luxembourgish */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'l':
+    if (lang_matches (&lang_str[1], "zh-hans"))
+    {
+      /* Literary Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'm':
+    if (lang_matches (&lang_str[1], "np-hant-hk"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hant-mo"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hans"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "np-hant"))
+    {
+      /* Min Bei Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Bei Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Bei Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "np-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Bei Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'n':
+    if (lang_matches (&lang_str[1], "an-hant-hk"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant-mo"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hans"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "an-hant"))
+    {
+      /* Min Nan Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Min Nan Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Min Nan Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "an-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Min Nan Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "o-bok"))
+    {
+      /* Norwegian Bokmal */
+      tags[0] = HB_TAG('N','O','R',' ');  /* Norwegian */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "o-nyn"))
+    {
+      /* Norwegian Nynorsk */
+      tags[0] = HB_TAG('N','Y','N',' ');  /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'r':
+    if (0 == strncmp (&lang_str[1], "o-", 2)
+        && subtag_matches (lang_str, limit, "-md"))
+    {
+      /* Romanian; Moldova */
+      tags[0] = HB_TAG('M','O','L',' ');  /* Moldavian */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'w':
+    if (lang_matches (&lang_str[1], "uu-hant-hk"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hant-mo"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hans"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "uu-hant"))
+    {
+      /* Wu Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Wu Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Wu Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "uu-", 3)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Wu Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'y':
+    if (lang_matches (&lang_str[1], "ue-hans"))
+    {
+      /* Yue Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    break;
+  case 'z':
+    if (lang_matches (&lang_str[1], "h-hant-hk"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hant-mo"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "h-min-nan"))
+    {
+      /* Minnan, Hokkien, Amoy, Taiwanese, Southern Min, Southern Fujian, Hoklo, Southern Fukien, Ho-lo */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hans"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (lang_matches (&lang_str[1], "h-hant"))
+    {
+      /* Chinese */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    if (0 == strcmp (&lang_str[1], "h-min"))
+    {
+      /* Min, Fuzhou, Hokkien, Amoy, or Taiwanese */
+      tags[0] = HB_TAG('Z','H','S',' ');  /* Chinese Simplified */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+        && subtag_matches (lang_str, limit, "-hk"))
+    {
+      /* Chinese; Hong Kong */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+        && subtag_matches (lang_str, limit, "-mo"))
+    {
+      /* Chinese; Macao */
+      tags[0] = HB_TAG('Z','H','H',' ');  /* Chinese, Hong Kong SAR */
+      *count = 1;
+      return true;
+    }
+    if (0 == strncmp (&lang_str[1], "h-", 2)
+        && subtag_matches (lang_str, limit, "-tw"))
+    {
+      /* Chinese; Taiwan, Province of China */
+      tags[0] = HB_TAG('Z','H','T',' ');  /* Chinese Traditional */
+      *count = 1;
+      return true;
+    }
+    break;
+  }
+  return false;
+}
+
+/**
+ * hb_ot_ambiguous_tag_to_language
+ * @tag: A language tag.
+ *
+ * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to
+ * many language tags) and the best tag is not the alphabetically first, or if
+ * the best tag consists of multiple subtags.
+ *
+ * Return value: The #hb_language_t corresponding to the BCP 47 language tag,
+ * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
+ **/
+static hb_language_t
+hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
+{
+  switch (tag)
+  {
+  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
+    return hb_language_from_string ("und-fonnapa", -1);  /* Undetermined; North American Phonetic Alphabet */
+  case HB_TAG('A','R','A',' '):  /* Arabic */
+    return hb_language_from_string ("ar", -1);  /* Arabic */
+  case HB_TAG('A','R','K',' '):  /* Rakhine */
+    return hb_language_from_string ("rki", -1);  /* Rakhine */
+  case HB_TAG('A','T','H',' '):  /* Athapaskan */
+    return hb_language_from_string ("ath", -1);  /* Athapascan */
+  case HB_TAG('B','I','K',' '):  /* Bikol */
+    return hb_language_from_string ("bik", -1);  /* Bikol */
+  case HB_TAG('C','P','P',' '):  /* Creoles */
+    return hb_language_from_string ("crp", -1);  /* Creoles and pidgins */
+  case HB_TAG('C','R','R',' '):  /* Carrier */
+    return hb_language_from_string ("crx", -1);  /* Carrier */
+  case HB_TAG('D','N','K',' '):  /* Dinka */
+    return hb_language_from_string ("din", -1);  /* Dinka */
+  case HB_TAG('D','R','I',' '):  /* Dari */
+    return hb_language_from_string ("prs", -1);  /* Dari */
+  case HB_TAG('D','U','J',' '):  /* Dhuwal */
+    return hb_language_from_string ("dwu", -1);  /* Dhuwal */
+  case HB_TAG('D','Z','N',' '):  /* Dzongkha */
+    return hb_language_from_string ("dz", -1);  /* Dzongkha */
+  case HB_TAG('E','T','I',' '):  /* Estonian */
+    return hb_language_from_string ("et", -1);  /* Estonian */
+  case HB_TAG('G','O','N',' '):  /* Gondi */
+    return hb_language_from_string ("gon", -1);  /* Gondi */
+  case HB_TAG('H','M','N',' '):  /* Hmong */
+    return hb_language_from_string ("hmn", -1);  /* Hmong */
+  case HB_TAG('I','J','O',' '):  /* Ijo */
+    return hb_language_from_string ("ijo", -1);  /* Ijo */
+  case HB_TAG('I','N','U',' '):  /* Inuktitut */
+    return hb_language_from_string ("iu", -1);  /* Inuktitut */
+  case HB_TAG('I','P','K',' '):  /* Inupiat */
+    return hb_language_from_string ("ik", -1);  /* Inupiaq */
+  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
+    return hb_language_from_string ("und-fonipa", -1);  /* Undetermined; International Phonetic Alphabet */
+  case HB_TAG('I','R','T',' '):  /* Irish Traditional */
+    return hb_language_from_string ("ga-Latg", -1);  /* Irish; Latin (Gaelic variant) */
+  case HB_TAG('J','I','I',' '):  /* Yiddish */
+    return hb_language_from_string ("yi", -1);  /* Yiddish */
+  case HB_TAG('K','A','L',' '):  /* Kalenjin */
+    return hb_language_from_string ("kln", -1);  /* Kalenjin */
+  case HB_TAG('K','G','E',' '):  /* Khutsuri Georgian */
+    return hb_language_from_string ("und-Geok", -1);  /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+  case HB_TAG('K','N','R',' '):  /* Kanuri */
+    return hb_language_from_string ("kr", -1);  /* Kanuri */
+  case HB_TAG('K','O','K',' '):  /* Konkani */
+    return hb_language_from_string ("kok", -1);  /* Konkani */
+  case HB_TAG('K','U','R',' '):  /* Kurdish */
+    return hb_language_from_string ("ku", -1);  /* Kurdish */
+  case HB_TAG('L','U','H',' '):  /* Luyia */
+    return hb_language_from_string ("luy", -1);  /* Luyia */
+  case HB_TAG('L','V','I',' '):  /* Latvian */
+    return hb_language_from_string ("lv", -1);  /* Latvian */
+  case HB_TAG('M','A','W',' '):  /* Marwari */
+    return hb_language_from_string ("mwr", -1);  /* Marwari */
+  case HB_TAG('M','L','G',' '):  /* Malagasy */
+    return hb_language_from_string ("mg", -1);  /* Malagasy */
+  case HB_TAG('M','L','Y',' '):  /* Malay */
+    return hb_language_from_string ("ms", -1);  /* Malay */
+  case HB_TAG('M','N','G',' '):  /* Mongolian */
+    return hb_language_from_string ("mn", -1);  /* Mongolian */
+  case HB_TAG('M','O','L',' '):  /* Moldavian */
+    return hb_language_from_string ("ro-MD", -1);  /* Romanian; Moldova */
+  case HB_TAG('N','E','P',' '):  /* Nepali */
+    return hb_language_from_string ("ne", -1);  /* Nepali */
+  case HB_TAG('N','I','S',' '):  /* Nisi */
+    return hb_language_from_string ("njz", -1);  /* Nyishi */
+  case HB_TAG('N','O','R',' '):  /* Norwegian */
+    return hb_language_from_string ("no", -1);  /* Norwegian */
+  case HB_TAG('O','J','B',' '):  /* Ojibway */
+    return hb_language_from_string ("oj", -1);  /* Ojibwa */
+  case HB_TAG('O','R','O',' '):  /* Oromo */
+    return hb_language_from_string ("om", -1);  /* Oromo */
+  case HB_TAG('P','A','S',' '):  /* Pashto */
+    return hb_language_from_string ("ps", -1);  /* Pashto */
+  case HB_TAG('P','G','R',' '):  /* Polytonic Greek */
+    return hb_language_from_string ("el-polyton", -1);  /* Modern Greek (1453-); Polytonic Greek */
+  case HB_TAG('P','R','O',' '):  /* Provençal / Old Provençal */
+    return hb_language_from_string ("pro", -1);  /* Old Provençal (to 1500) */
+  case HB_TAG('Q','U','H',' '):  /* Quechua (Bolivia) */
+    return hb_language_from_string ("quh", -1);  /* South Bolivian Quechua */
+  case HB_TAG('Q','V','I',' '):  /* Quechua (Ecuador) */
+    return hb_language_from_string ("qvi", -1);  /* Imbabura Highland Quichua */
+  case HB_TAG('Q','W','H',' '):  /* Quechua (Peru) */
+    return hb_language_from_string ("qwh", -1);  /* Huaylas Ancash Quechua */
+  case HB_TAG('R','A','J',' '):  /* Rajasthani */
+    return hb_language_from_string ("raj", -1);  /* Rajasthani */
+  case HB_TAG('R','O','Y',' '):  /* Romany */
+    return hb_language_from_string ("rom", -1);  /* Romany */
+  case HB_TAG('S','Q','I',' '):  /* Albanian */
+    return hb_language_from_string ("sq", -1);  /* Albanian */
+  case HB_TAG('S','Y','R',' '):  /* Syriac */
+    return hb_language_from_string ("syr", -1);  /* Syriac */
+  case HB_TAG('S','Y','R','E'):  /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+    return hb_language_from_string ("und-Syre", -1);  /* Undetermined; Syriac (Estrangelo variant) */
+  case HB_TAG('S','Y','R','J'):  /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+    return hb_language_from_string ("und-Syrj", -1);  /* Undetermined; Syriac (Western variant) */
+  case HB_TAG('S','Y','R','N'):  /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+    return hb_language_from_string ("und-Syrn", -1);  /* Undetermined; Syriac (Eastern variant) */
+  case HB_TAG('T','M','H',' '):  /* Tamashek */
+    return hb_language_from_string ("tmh", -1);  /* Tamashek */
+  case HB_TAG('T','N','E',' '):  /* Tundra Nenets */
+    return hb_language_from_string ("yrk", -1);  /* Nenets */
+  case HB_TAG('Z','H','H',' '):  /* Chinese, Hong Kong SAR */
+    return hb_language_from_string ("zh-HK", -1);  /* Chinese; Hong Kong */
+  case HB_TAG('Z','H','S',' '):  /* Chinese Simplified */
+    return hb_language_from_string ("zh-Hans", -1);  /* Chinese; Han (Simplified variant) */
+  case HB_TAG('Z','H','T',' '):  /* Chinese Traditional */
+    return hb_language_from_string ("zh-Hant", -1);  /* Chinese; Han (Traditional variant) */
+  default:
+    return HB_LANGUAGE_INVALID;
+  }
+}
+
+#endif /* HB_OT_TAG_TABLE_HH */
+
+/* == End of generated table == */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,7 +26,7 @@
  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 
 /* hb_script_t */
@@ -36,7 +36,8 @@
 {
   /* This seems to be accurate as of end of 2012. */
 
-  switch ((hb_tag_t) script) {
+  switch ((hb_tag_t) script)
+  {
     case HB_SCRIPT_INVALID:             return HB_OT_TAG_DEFAULT_SCRIPT;
 
     /* KATAKANA and HIRAGANA both map to 'kana' */
@@ -49,8 +50,6 @@
     case HB_SCRIPT_NKO:                 return HB_TAG('n','k','o',' ');
     /* Unicode-5.1 additions */
     case HB_SCRIPT_VAI:                 return HB_TAG('v','a','i',' ');
-    /* Unicode-5.2 additions */
-    /* Unicode-6.0 additions */
   }
 
   /* Else, just change first char to lowercase and return */
@@ -114,6 +113,18 @@
   return HB_SCRIPT_UNKNOWN;
 }
 
+void
+hb_ot_tags_from_script (hb_script_t  script,
+                        hb_tag_t    *script_tag_1,
+                        hb_tag_t    *script_tag_2)
+{
+  unsigned int count = 2;
+  hb_tag_t tags[2];
+  hb_ot_tags_from_script_and_language (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr);
+  *script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT;
+  *script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT;
+}
+
 /*
  * Complete list at:
  * https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags
@@ -122,28 +133,37 @@
  * So we just do that, and handle the exceptional cases in a switch.
  */
 
-void
-hb_ot_tags_from_script (hb_script_t  script,
-                        hb_tag_t    *script_tag_1,
-                        hb_tag_t    *script_tag_2)
+static void
+hb_ot_all_tags_from_script (hb_script_t   script,
+                            unsigned int *count /* IN/OUT */,
+                            hb_tag_t     *tags /* OUT */)
 {
-  hb_tag_t new_tag;
+  unsigned int i = 0;
 
-  *script_tag_2 = HB_OT_TAG_DEFAULT_SCRIPT;
-  *script_tag_1 = hb_ot_old_tag_from_script (script);
+  hb_tag_t new_tag = hb_ot_new_tag_from_script (script);
+  if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT))
+  {
+    tags[i++] = new_tag | '3';
+    if (*count > i)
+      tags[i++] = new_tag;
+  }
 
-  new_tag = hb_ot_new_tag_from_script (script);
-  if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT)) {
-    *script_tag_2 = *script_tag_1;
-    *script_tag_1 = new_tag;
+  if (*count > i)
+  {
+    hb_tag_t old_tag = hb_ot_old_tag_from_script (script);
+    if (old_tag != HB_OT_TAG_DEFAULT_SCRIPT)
+      tags[i++] = old_tag;
   }
+
+  *count = i;
 }
 
 hb_script_t
 hb_ot_tag_to_script (hb_tag_t tag)
 {
-  if (unlikely ((tag & 0x000000FFu) == '2'))
-    return hb_ot_new_tag_to_script (tag);
+  unsigned char digit = tag & 0x000000FFu;
+  if (unlikely (digit == '2' || digit == '3'))
+    return hb_ot_new_tag_to_script (tag & 0xFFFFFF32);
 
   return hb_ot_old_tag_to_script (tag);
 }
@@ -151,732 +171,6 @@
 
 /* hb_language_t */
 
-typedef struct {
-  char language[4];
-  hb_tag_t tag;
-} LangTag;
-
-/*
- * Complete list at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
- *
- * Generated by intersecting the OpenType language tag list from
- * Draft OpenType 1.5 spec, with with the ISO 639-3 codes from
- * 2008-08-04, matching on name, and finally adjusted manually.
- *
- * Updated on 2012-12-07 with more research into remaining codes.
- *
- * Updated on 2013-11-23 based on usage in SIL and Microsoft fonts,
- * the new proposal from Microsoft, and latest ISO 639-3 names.
- *
- * Some items still missing.  Those are commented out at the end.
- * Keep sorted for bsearch.
- *
- * Updated as of 2015-05-06: OT1.7 on MS website has some newer
- * items that we don't have here, eg. Zazaki.  This is the new
- * items in OpenType 1.7 (red items), most of which we have:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/languagetags
- */
-
-static const LangTag ot_languages[] = {
-  {"aa",        HB_TAG('A','F','R',' ')},       /* Afar */
-  {"ab",        HB_TAG('A','B','K',' ')},       /* Abkhazian */
-  {"abq",       HB_TAG('A','B','A',' ')},       /* Abaza */
-  {"acf",       HB_TAG('F','A','N',' ')},       /* French Antillean */
-  {"ach",       HB_TAG('A','C','H',' ')},       /* Acoli */
-  {"acr",       HB_TAG('A','C','R',' ')},       /* Achi */
-  {"ada",       HB_TAG('D','N','G',' ')},       /* Dangme */
-  {"ady",       HB_TAG('A','D','Y',' ')},       /* Adyghe */
-  {"af",        HB_TAG('A','F','K',' ')},       /* Afrikaans */
-  {"ahg",       HB_TAG('A','G','W',' ')},       /* Agaw */
-  {"aii",       HB_TAG('S','W','A',' ')},       /* Swadaya Aramaic */
-  {"aio",       HB_TAG('A','I','O',' ')},       /* Aiton */
-  {"aiw",       HB_TAG('A','R','I',' ')},       /* Aari */
-  {"ak",        HB_TAG('T','W','I',' ')},       /* Akan [macrolanguage] */
-  {"aka",       HB_TAG('A','K','A',' ')},       /* Akan */
-  {"alt",       HB_TAG('A','L','T',' ')},       /* [Southern] Altai */
-  {"am",        HB_TAG('A','M','H',' ')},       /* Amharic */
-  {"amf",       HB_TAG('H','B','N',' ')},       /* Hammer-Banna */
-  {"amw",       HB_TAG('S','Y','R',' ')},       /* Western Neo-Aramaic */
-  {"an",        HB_TAG('A','R','G',' ')},       /* Aragonese */
-  {"ang",       HB_TAG('A','N','G',' ')},       /* Old English (ca. 450-1100) */
-  {"ar",        HB_TAG('A','R','A',' ')},       /* Arabic [macrolanguage] */
-  {"arb",       HB_TAG('A','R','A',' ')},       /* Standard Arabic */
-  {"arn",       HB_TAG('M','A','P',' ')},       /* Mapudungun */
-  {"ary",       HB_TAG('M','O','R',' ')},       /* Moroccan Arabic */
-  {"as",        HB_TAG('A','S','M',' ')},       /* Assamese */
-  {"ast",       HB_TAG('A','S','T',' ')},       /* Asturian/Asturleonese/Bable/Leonese */
-  {"ath",       HB_TAG('A','T','H',' ')},       /* Athapaskan [family] */
-  {"atj",       HB_TAG('R','C','R',' ')},       /* R-Cree */
-  {"atv",       HB_TAG('A','L','T',' ')},       /* [Northern] Altai */
-  {"av",        HB_TAG('A','V','R',' ')},       /* Avaric */
-  {"awa",       HB_TAG('A','W','A',' ')},       /* Awadhi */
-  {"ay",        HB_TAG('A','Y','M',' ')},       /* Aymara [macrolanguage] */
-  {"az",        HB_TAG('A','Z','E',' ')},       /* Azerbaijani [macrolanguage] */
-  {"azb",       HB_TAG('A','Z','B',' ')},       /* South Azerbaijani */
-  {"azj",       HB_TAG('A','Z','E',' ')},       /* North Azerbaijani */
-  {"ba",        HB_TAG('B','S','H',' ')},       /* Bashkir */
-  {"bad",       HB_TAG('B','A','D','0')},       /* Banda */
-  {"bai",       HB_TAG('B','M','L',' ')},       /* Bamileke [family] */
-  {"bal",       HB_TAG('B','L','I',' ')},       /* Baluchi [macrolangauge] */
-  {"ban",       HB_TAG('B','A','N',' ')},       /* Balinese */
-  {"bar",       HB_TAG('B','A','R',' ')},       /* Bavarian */
-  {"bbc",       HB_TAG('B','B','C',' ')},       /* Batak Toba */
-  {"bci",       HB_TAG('B','A','U',' ')},       /* Baoulé */
-  {"bcl",       HB_TAG('B','I','K',' ')},       /* Central Bikol */
-  {"bcq",       HB_TAG('B','C','H',' ')},       /* Bench */
-  {"bdy",       HB_TAG('B','D','Y',' ')},       /* Bandjalang */
-  {"be",        HB_TAG('B','E','L',' ')},       /* Belarusian */
-  {"bem",       HB_TAG('B','E','M',' ')},       /* Bemba (Zambia) */
-  {"ber",       HB_TAG('B','E','R',' ')},       /* Berber [family] */
-  {"bfq",       HB_TAG('B','A','D',' ')},       /* Badaga */
-  {"bft",       HB_TAG('B','L','T',' ')},       /* Balti */
-  {"bfu",       HB_TAG('L','A','H',' ')},       /* Lahuli */
-  {"bfy",       HB_TAG('B','A','G',' ')},       /* Baghelkhandi */
-  {"bg",        HB_TAG('B','G','R',' ')},       /* Bulgarian */
-  {"bgc",       HB_TAG('B','G','C',' ')},       /* Haryanvi */
-  {"bgq",       HB_TAG('B','G','Q',' ')},       /* Bagri */
-  {"bgr",       HB_TAG('Q','I','N',' ')},       /* Bawm Chin */
-  {"bhb",       HB_TAG('B','H','I',' ')},       /* Bhili */
-  {"bhk",       HB_TAG('B','I','K',' ')},       /* Albay Bicolano (retired code) */
-  {"bho",       HB_TAG('B','H','O',' ')},       /* Bhojpuri */
-  {"bi",        HB_TAG('B','I','S',' ')},       /* Bislama */
-  {"bik",       HB_TAG('B','I','K',' ')},       /* Bikol [macrolanguage] */
-  {"bin",       HB_TAG('E','D','O',' ')},       /* Bini */
-  {"bjj",       HB_TAG('B','J','J',' ')},       /* Kanauji */
-  {"bjt",       HB_TAG('B','L','N',' ')},       /* Balanta-Ganja */
-  {"bla",       HB_TAG('B','K','F',' ')},       /* Blackfoot */
-  {"ble",       HB_TAG('B','L','N',' ')},       /* Balanta-Kentohe */
-  {"blk",       HB_TAG('B','L','K',' ')},       /* Pa'O/Pa'o Karen */
-  {"bln",       HB_TAG('B','I','K',' ')},       /* Southern Catanduanes Bikol */
-  {"bm",        HB_TAG('B','M','B',' ')},       /* Bambara */
-  {"bn",        HB_TAG('B','E','N',' ')},       /* Bengali */
-  {"bo",        HB_TAG('T','I','B',' ')},       /* Tibetan */
-  {"bpy",       HB_TAG('B','P','Y',' ')},       /* Bishnupriya */
-  {"bqi",       HB_TAG('L','R','C',' ')},       /* Bakhtiari */
-  {"br",        HB_TAG('B','R','E',' ')},       /* Breton */
-  {"bra",       HB_TAG('B','R','I',' ')},       /* Braj Bhasha */
-  {"brh",       HB_TAG('B','R','H',' ')},       /* Brahui */
-  {"brx",       HB_TAG('B','R','X',' ')},       /* Bodo (India) */
-  {"bs",        HB_TAG('B','O','S',' ')},       /* Bosnian */
-  {"btb",       HB_TAG('B','T','I',' ')},       /* Beti (Cameroon) */
-  {"bto",       HB_TAG('B','I','K',' ')},       /* Rinconada Bikol */
-  {"bts",       HB_TAG('B','T','S',' ')},       /* Batak Simalungun */
-  {"bug",       HB_TAG('B','U','G',' ')},       /* Buginese */
-  {"bxr",       HB_TAG('R','B','U',' ')},       /* Russian Buriat */
-  {"byn",       HB_TAG('B','I','L',' ')},       /* Bilen */
-  {"ca",        HB_TAG('C','A','T',' ')},       /* Catalan */
-  {"cak",       HB_TAG('C','A','K',' ')},       /* Kaqchikel */
-  {"cbk",       HB_TAG('C','B','K',' ')},       /* Chavacano */
-  {"cbl",       HB_TAG('Q','I','N',' ')},       /* Bualkhaw Chin */
-  {"cco",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"ce",        HB_TAG('C','H','E',' ')},       /* Chechen */
-  {"ceb",       HB_TAG('C','E','B',' ')},       /* Cebuano */
-  {"cfm",       HB_TAG('H','A','L',' ')},       /* Halam/Falam Chin */
-  {"cgg",       HB_TAG('C','G','G',' ')},       /* Chiga */
-  {"ch",        HB_TAG('C','H','A',' ')},       /* Chamorro */
-  {"chj",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"chk",       HB_TAG('C','H','K','0')},       /* Chuukese */
-  {"cho",       HB_TAG('C','H','O',' ')},       /* Choctaw */
-  {"chp",       HB_TAG('C','H','P',' ')},       /* Chipewyan */
-  {"chq",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"chr",       HB_TAG('C','H','R',' ')},       /* Cherokee */
-  {"chy",       HB_TAG('C','H','Y',' ')},       /* Cheyenne */
-  {"chz",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cja",       HB_TAG('C','J','A',' ')},       /* Western Cham */
-  {"cjm",       HB_TAG('C','J','M',' ')},       /* Eastern Cham */
-  {"cka",       HB_TAG('Q','I','N',' ')},       /* Khumi Awa Chin */
-  {"ckb",       HB_TAG('K','U','R',' ')},       /* Central Kurdish (Sorani) */
-  {"ckt",       HB_TAG('C','H','K',' ')},       /* Chukchi */
-  {"cld",       HB_TAG('S','Y','R',' ')},       /* Chaldean Neo-Aramaic */
-  {"cle",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cmr",       HB_TAG('Q','I','N',' ')},       /* Mro-Khimi Chin */
-  {"cnb",       HB_TAG('Q','I','N',' ')},       /* Chinbon Chin */
-  {"cnh",       HB_TAG('Q','I','N',' ')},       /* Hakha Chin */
-  {"cnk",       HB_TAG('Q','I','N',' ')},       /* Khumi Chin */
-  {"cnl",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cnt",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cnw",       HB_TAG('Q','I','N',' ')},       /* Ngawn Chin */
-  {"cop",       HB_TAG('C','O','P',' ')},       /* Coptic */
-  {"cpa",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cpp",       HB_TAG('C','P','P',' ')},       /* Creoles */
-  {"cr",        HB_TAG('C','R','E',' ')},       /* Cree */
-  {"cre",       HB_TAG('Y','C','R',' ')},       /* Y-Cree */
-  {"crh",       HB_TAG('C','R','T',' ')},       /* Crimean Tatar */
-  {"crj",       HB_TAG('E','C','R',' ')},       /* [Southern] East Cree */
-  {"crk",       HB_TAG('W','C','R',' ')},       /* West-Cree */
-  {"crl",       HB_TAG('E','C','R',' ')},       /* [Northern] East Cree */
-  {"crm",       HB_TAG('M','C','R',' ')},       /* Moose Cree */
-  {"crx",       HB_TAG('C','R','R',' ')},       /* Carrier */
-  {"cs",        HB_TAG('C','S','Y',' ')},       /* Czech */
-  {"csa",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"csb",       HB_TAG('C','S','B',' ')},       /* Kashubian */
-  {"csh",       HB_TAG('Q','I','N',' ')},       /* Asho Chin */
-  {"cso",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"csy",       HB_TAG('Q','I','N',' ')},       /* Siyin Chin */
-  {"ctd",       HB_TAG('Q','I','N',' ')},       /* Tedim Chin */
-  {"cte",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"ctg",       HB_TAG('C','T','G',' ')},       /* Chittagonian */
-  {"ctl",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cts",       HB_TAG('B','I','K',' ')},       /* Northern Catanduanes Bikol */
-  {"cu",        HB_TAG('C','S','L',' ')},       /* Church Slavic */
-  {"cuc",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cuk",       HB_TAG('C','U','K',' ')},       /* San Blas Kuna */
-  {"cv",        HB_TAG('C','H','U',' ')},       /* Chuvash */
-  {"cvn",       HB_TAG('C','C','H','N')},       /* Chinantec */
-  {"cwd",       HB_TAG('D','C','R',' ')},       /* Woods Cree */
-  {"cy",        HB_TAG('W','E','L',' ')},       /* Welsh */
-  {"czt",       HB_TAG('Q','I','N',' ')},       /* Zotung Chin */
-  {"da",        HB_TAG('D','A','N',' ')},       /* Danish */
-  {"dao",       HB_TAG('Q','I','N',' ')},       /* Daai Chin */
-  {"dap",       HB_TAG('N','I','S',' ')},       /* Nisi (India) */
-  {"dar",       HB_TAG('D','A','R',' ')},       /* Dargwa */
-  {"dax",       HB_TAG('D','A','X',' ')},       /* Dayi */
-  {"de",        HB_TAG('D','E','U',' ')},       /* German */
-  {"dgo",       HB_TAG('D','G','O',' ')},       /* Dogri */
-  {"dhd",       HB_TAG('M','A','W',' ')},       /* Dhundari */
-  {"dhg",       HB_TAG('D','H','G',' ')},       /* Dhangu */
-  {"din",       HB_TAG('D','N','K',' ')},       /* Dinka [macrolanguage] */
-  {"diq",       HB_TAG('D','I','Q',' ')},       /* Dimli */
-  {"dje",       HB_TAG('D','J','R',' ')},       /* Zarma */
-  {"djr",       HB_TAG('D','J','R','0')},       /* Djambarrpuyngu */
-  {"dng",       HB_TAG('D','U','N',' ')},       /* Dungan */
-  {"dnj",       HB_TAG('D','N','J',' ')},       /* Dan */
-  {"doi",       HB_TAG('D','G','R',' ')},       /* Dogri [macrolanguage] */
-  {"dsb",       HB_TAG('L','S','B',' ')},       /* Lower Sorbian */
-  {"duj",       HB_TAG('D','U','J',' ')},       /* Dhuwal */
-  {"dv",        HB_TAG('D','I','V',' ')},       /* Dhivehi/Divehi/Maldivian */
-  {"dyu",       HB_TAG('J','U','L',' ')},       /* Jula */
-  {"dz",        HB_TAG('D','Z','N',' ')},       /* Dzongkha */
-  {"ee",        HB_TAG('E','W','E',' ')},       /* Ewe */
-  {"efi",       HB_TAG('E','F','I',' ')},       /* Efik */
-  {"ekk",       HB_TAG('E','T','I',' ')},       /* Standard Estonian */
-  {"el",        HB_TAG('E','L','L',' ')},       /* Modern Greek (1453-) */
-  {"emk",       HB_TAG('M','N','K',' ')},       /* Eastern Maninkakan */
-  {"en",        HB_TAG('E','N','G',' ')},       /* English */
-  {"enf",       HB_TAG('F','N','E',' ')},       /* Forest Nenets */
-  {"enh",       HB_TAG('T','N','E',' ')},       /* Tundra Nenets */
-  {"eo",        HB_TAG('N','T','O',' ')},       /* Esperanto */
-  {"eot",       HB_TAG('B','T','I',' ')},       /* Beti (Côte d'Ivoire) */
-  {"es",        HB_TAG('E','S','P',' ')},       /* Spanish */
-  {"esu",       HB_TAG('E','S','U',' ')},       /* Central Yupik */
-  {"et",        HB_TAG('E','T','I',' ')},       /* Estonian [macrolanguage] */
-  {"eu",        HB_TAG('E','U','Q',' ')},       /* Basque */
-  {"eve",       HB_TAG('E','V','N',' ')},       /* Even */
-  {"evn",       HB_TAG('E','V','K',' ')},       /* Evenki */
-  {"fa",        HB_TAG('F','A','R',' ')},       /* Persian [macrolanguage] */
-  {"fan",       HB_TAG('F','A','N','0')},       /* Fang */
-  {"fat",       HB_TAG('F','A','T',' ')},       /* Fanti */
-  {"ff",        HB_TAG('F','U','L',' ')},       /* Fulah [macrolanguage] */
-  {"fi",        HB_TAG('F','I','N',' ')},       /* Finnish */
-  {"fil",       HB_TAG('P','I','L',' ')},       /* Filipino */
-  {"fj",        HB_TAG('F','J','I',' ')},       /* Fijian */
-  {"flm",       HB_TAG('H','A','L',' ')},       /* Halam/Falam Chin [retired ISO639 code] */
-  {"fo",        HB_TAG('F','O','S',' ')},       /* Faroese */
-  {"fon",       HB_TAG('F','O','N',' ')},       /* Fon */
-  {"fr",        HB_TAG('F','R','A',' ')},       /* French */
-  {"frc",       HB_TAG('F','R','C',' ')},       /* Cajun French */
-  {"frp",       HB_TAG('F','R','P',' ')},       /* Arpitan/Francoprovençal */
-  {"fuf",       HB_TAG('F','T','A',' ')},       /* Futa */
-  {"fur",       HB_TAG('F','R','L',' ')},       /* Friulian */
-  {"fuv",       HB_TAG('F','U','V',' ')},       /* Nigerian Fulfulde */
-  {"fy",        HB_TAG('F','R','I',' ')},       /* Western Frisian */
-  {"ga",        HB_TAG('I','R','I',' ')},       /* Irish */
-  {"gaa",       HB_TAG('G','A','D',' ')},       /* Ga */
-  {"gag",       HB_TAG('G','A','G',' ')},       /* Gagauz */
-  {"gbm",       HB_TAG('G','A','W',' ')},       /* Garhwali */
-  {"gd",        HB_TAG('G','A','E',' ')},       /* Scottish Gaelic */
-  {"gez",       HB_TAG('G','E','Z',' ')},       /* Ge'ez */
-  {"ggo",       HB_TAG('G','O','N',' ')},       /* Southern Gondi */
-  {"gih",       HB_TAG('G','I','H',' ')},       /* Githabul */
-  {"gil",       HB_TAG('G','I','L','0')},       /* Kiribati (Gilbertese) */
-  {"gkp",       HB_TAG('G','K','P',' ')},       /* Kpelle (Guinea) */
-  {"gl",        HB_TAG('G','A','L',' ')},       /* Galician */
-  {"gld",       HB_TAG('N','A','N',' ')},       /* Nanai */
-  {"glk",       HB_TAG('G','L','K',' ')},       /* Gilaki */
-  {"gn",        HB_TAG('G','U','A',' ')},       /* Guarani [macrolanguage] */
-  {"gnn",       HB_TAG('G','N','N',' ')},       /* Gumatj */
-  {"gno",       HB_TAG('G','O','N',' ')},       /* Northern Gondi */
-  {"gog",       HB_TAG('G','O','G',' ')},       /* Gogo */
-  {"gon",       HB_TAG('G','O','N',' ')},       /* Gondi [macrolanguage] */
-  {"grt",       HB_TAG('G','R','O',' ')},       /* Garo */
-  {"gru",       HB_TAG('S','O','G',' ')},       /* Sodo Gurage */
-  {"gsw",       HB_TAG('A','L','S',' ')},       /* Alsatian */
-  {"gu",        HB_TAG('G','U','J',' ')},       /* Gujarati */
-  {"guc",       HB_TAG('G','U','C',' ')},       /* Wayuu */
-  {"guf",       HB_TAG('G','U','F',' ')},       /* Gupapuyngu */
-  {"guk",       HB_TAG('G','M','Z',' ')},       /* Gumuz */
-/*{"guk",       HB_TAG('G','U','K',' ')},*/     /* Gumuz (in SIL fonts) */
-  {"guz",       HB_TAG('G','U','Z',' ')},       /* Ekegusii/Gusii */
-  {"gv",        HB_TAG('M','N','X',' ')},       /* Manx */
-  {"ha",        HB_TAG('H','A','U',' ')},       /* Hausa */
-  {"har",       HB_TAG('H','R','I',' ')},       /* Harari */
-  {"haw",       HB_TAG('H','A','W',' ')},       /* Hawaiian */
-  {"hay",       HB_TAG('H','A','Y',' ')},       /* Haya */
-  {"haz",       HB_TAG('H','A','Z',' ')},       /* Hazaragi */
-  {"he",        HB_TAG('I','W','R',' ')},       /* Hebrew */
-  {"hi",        HB_TAG('H','I','N',' ')},       /* Hindi */
-  {"hil",       HB_TAG('H','I','L',' ')},       /* Hiligaynon */
-  {"hlt",       HB_TAG('Q','I','N',' ')},       /* Matu Chin */
-  {"hmn",       HB_TAG('H','M','N',' ')},       /* Hmong */
-  {"hnd",       HB_TAG('H','N','D',' ')},       /* [Southern] Hindko */
-  {"hne",       HB_TAG('C','H','H',' ')},       /* Chattisgarhi */
-  {"hno",       HB_TAG('H','N','D',' ')},       /* [Northern] Hindko */
-  {"ho",        HB_TAG('H','M','O',' ')},       /* Hiri Motu */
-  {"hoc",       HB_TAG('H','O',' ',' ')},       /* Ho */
-  {"hoj",       HB_TAG('H','A','R',' ')},       /* Harauti */
-  {"hr",        HB_TAG('H','R','V',' ')},       /* Croatian */
-  {"hsb",       HB_TAG('U','S','B',' ')},       /* Upper Sorbian */
-  {"ht",        HB_TAG('H','A','I',' ')},       /* Haitian/Haitian Creole */
-  {"hu",        HB_TAG('H','U','N',' ')},       /* Hungarian */
-  {"hy",        HB_TAG('H','Y','E',' ')},       /* Armenian */
-  {"hz",        HB_TAG('H','E','R',' ')},       /* Herero */
-  {"ia",        HB_TAG('I','N','A',' ')},       /* Interlingua (International Auxiliary Language Association) */
-  {"iba",       HB_TAG('I','B','A',' ')},       /* Iban */
-  {"ibb",       HB_TAG('I','B','B',' ')},       /* Ibibio */
-  {"id",        HB_TAG('I','N','D',' ')},       /* Indonesian */
-  {"ie",        HB_TAG('I','L','E',' ')},       /* Interlingue/Occidental */
-  {"ig",        HB_TAG('I','B','O',' ')},       /* Igbo */
-  {"igb",       HB_TAG('E','B','I',' ')},       /* Ebira */
-  {"ii",        HB_TAG('Y','I','M',' ')},       /* Yi Modern */
-  {"ijc",       HB_TAG('I','J','O',' ')},       /* Izon */
-  {"ijo",       HB_TAG('I','J','O',' ')},       /* Ijo [family] */
-  {"ik",        HB_TAG('I','P','K',' ')},       /* Inupiaq [macrolanguage] */
-  {"ilo",       HB_TAG('I','L','O',' ')},       /* Ilokano */
-  {"inh",       HB_TAG('I','N','G',' ')},       /* Ingush */
-  {"io",        HB_TAG('I','D','O',' ')},       /* Ido */
-  {"is",        HB_TAG('I','S','L',' ')},       /* Icelandic */
-  {"it",        HB_TAG('I','T','A',' ')},       /* Italian */
-  {"iu",        HB_TAG('I','N','U',' ')},       /* Inuktitut [macrolanguage] */
-  {"ja",        HB_TAG('J','A','N',' ')},       /* Japanese */
-  {"jam",       HB_TAG('J','A','M',' ')},       /* Jamaican Creole English */
-  {"jbo",       HB_TAG('J','B','O',' ')},       /* Lojban */
-  {"jv",        HB_TAG('J','A','V',' ')},       /* Javanese */
-  {"ka",        HB_TAG('K','A','T',' ')},       /* Georgian */
-  {"kaa",       HB_TAG('K','R','K',' ')},       /* Karakalpak */
-  {"kab",       HB_TAG('K','A','B','0')},       /* Kabyle */
-  {"kam",       HB_TAG('K','M','B',' ')},       /* Kamba (Kenya) */
-  {"kar",       HB_TAG('K','R','N',' ')},       /* Karen [family] */
-  {"kat",       HB_TAG('K','G','E',' ')},       /* Khutsuri Georgian */
-  {"kbd",       HB_TAG('K','A','B',' ')},       /* Kabardian */
-  {"kde",       HB_TAG('K','D','E',' ')},       /* Makonde */
-  {"kdr",       HB_TAG('K','R','M',' ')},       /* Karaim */
-  {"kdt",       HB_TAG('K','U','Y',' ')},       /* Kuy */
-  {"kea",       HB_TAG('K','E','A',' ')},       /* Kabuverdianu (Crioulo) */
-  {"kek",       HB_TAG('K','E','K',' ')},       /* Kekchi */
-  {"kex",       HB_TAG('K','K','N',' ')},       /* Kokni */
-  {"kfa",       HB_TAG('K','O','D',' ')},       /* Kodagu */
-  {"kfr",       HB_TAG('K','A','C',' ')},       /* Kachchi */
-  {"kfx",       HB_TAG('K','U','L',' ')},       /* Kulvi */
-  {"kfy",       HB_TAG('K','M','N',' ')},       /* Kumaoni */
-  {"kg",        HB_TAG('K','O','N',' ')},       /* Kongo [macrolanguage] */
-  {"kha",       HB_TAG('K','S','I',' ')},       /* Khasi */
-  {"khb",       HB_TAG('X','B','D',' ')},       /* Lü */
-  {"kht",       HB_TAG('K','H','N',' ')},       /* Khamti (Microsoft fonts) */
-/*{"kht",       HB_TAG('K','H','T',' ')},*/     /* Khamti (OpenType spec and SIL fonts) */
-  {"khw",       HB_TAG('K','H','W',' ')},       /* Khowar */
-  {"ki",        HB_TAG('K','I','K',' ')},       /* Gikuyu/Kikuyu */
-  {"kiu",       HB_TAG('K','I','U',' ')},       /* Kirmanjki */
-  {"kj",        HB_TAG('K','U','A',' ')},       /* Kuanyama/Kwanyama */
-  {"kjd",       HB_TAG('K','J','D',' ')},       /* Southern Kiwai */
-  {"kjh",       HB_TAG('K','H','A',' ')},       /* Khakass */
-  {"kjp",       HB_TAG('K','J','P',' ')},       /* Pwo Eastern Karen */
-  {"kk",        HB_TAG('K','A','Z',' ')},       /* Kazakh */
-  {"kl",        HB_TAG('G','R','N',' ')},       /* Kalaallisut */
-  {"kln",       HB_TAG('K','A','L',' ')},       /* Kalenjin */
-  {"km",        HB_TAG('K','H','M',' ')},       /* Central Khmer */
-  {"kmb",       HB_TAG('M','B','N',' ')},       /* Kimbundu */
-  {"kmw",       HB_TAG('K','M','O',' ')},       /* Komo (Democratic Republic of Congo) */
-  {"kn",        HB_TAG('K','A','N',' ')},       /* Kannada */
-  {"knn",       HB_TAG('K','O','K',' ')},       /* Konkani */
-  {"ko",        HB_TAG('K','O','R',' ')},       /* Korean */
-  {"koi",       HB_TAG('K','O','P',' ')},       /* Komi-Permyak */
-  {"kok",       HB_TAG('K','O','K',' ')},       /* Konkani [macrolanguage] */
-  {"kon",       HB_TAG('K','O','N','0')},       /* Kongo */
-  {"kos",       HB_TAG('K','O','S',' ')},       /* Kosraean */
-  {"kpe",       HB_TAG('K','P','L',' ')},       /* Kpelle [macrolanguage] */
-  {"kpv",       HB_TAG('K','O','Z',' ')},       /* Komi-Zyrian */
-  {"kpy",       HB_TAG('K','Y','K',' ')},       /* Koryak */
-  {"kqy",       HB_TAG('K','R','T',' ')},       /* Koorete */
-  {"kr",        HB_TAG('K','N','R',' ')},       /* Kanuri [macrolanguage] */
-  {"kri",       HB_TAG('K','R','I',' ')},       /* Krio */
-  {"krl",       HB_TAG('K','R','L',' ')},       /* Karelian */
-  {"kru",       HB_TAG('K','U','U',' ')},       /* Kurukh */
-  {"ks",        HB_TAG('K','S','H',' ')},       /* Kashmiri */
-  {"ksh",       HB_TAG('K','S','H','0')},       /* Ripuarian, Kölsch */
-/*{"ksw",       HB_TAG('K','R','N',' ')},*/     /* S'gaw Karen (Microsoft fonts?) */
-  {"ksw",       HB_TAG('K','S','W',' ')},       /* S'gaw Karen (OpenType spec and SIL fonts) */
-  {"ktb",       HB_TAG('K','E','B',' ')},       /* Kebena */
-  {"ktu",       HB_TAG('K','O','N',' ')},       /* Kikongo */
-  {"ku",        HB_TAG('K','U','R',' ')},       /* Kurdish [macrolanguage] */
-  {"kum",       HB_TAG('K','U','M',' ')},       /* Kumyk */
-  {"kv",        HB_TAG('K','O','M',' ')},       /* Komi [macrolanguage] */
-  {"kvd",       HB_TAG('K','U','I',' ')},       /* Kui (Indonesia) */
-  {"kw",        HB_TAG('C','O','R',' ')},       /* Cornish */
-  {"kxc",       HB_TAG('K','M','S',' ')},       /* Komso */
-  {"kxu",       HB_TAG('K','U','I',' ')},       /* Kui (India) */
-  {"ky",        HB_TAG('K','I','R',' ')},       /* Kirghiz/Kyrgyz */
-  {"kyu",       HB_TAG('K','Y','U',' ')},       /* Western Kayah */
-  {"la",        HB_TAG('L','A','T',' ')},       /* Latin */
-  {"lad",       HB_TAG('J','U','D',' ')},       /* Ladino */
-  {"lb",        HB_TAG('L','T','Z',' ')},       /* Luxembourgish */
-  {"lbe",       HB_TAG('L','A','K',' ')},       /* Lak */
-  {"lbj",       HB_TAG('L','D','K',' ')},       /* Ladakhi */
-  {"lez",       HB_TAG('L','E','Z',' ')},       /* Lezgi */
-  {"lg",        HB_TAG('L','U','G',' ')},       /* Ganda */
-  {"li",        HB_TAG('L','I','M',' ')},       /* Limburgan/Limburger/Limburgish */
-  {"lif",       HB_TAG('L','M','B',' ')},       /* Limbu */
-  {"lij",       HB_TAG('L','I','J',' ')},       /* Ligurian */
-  {"lis",       HB_TAG('L','I','S',' ')},       /* Lisu */
-  {"ljp",       HB_TAG('L','J','P',' ')},       /* Lampung Api */
-  {"lki",       HB_TAG('L','K','I',' ')},       /* Laki */
-  {"lld",       HB_TAG('L','A','D',' ')},       /* Ladin */
-  {"lmn",       HB_TAG('L','A','M',' ')},       /* Lambani */
-  {"lmo",       HB_TAG('L','M','O',' ')},       /* Lombard */
-  {"ln",        HB_TAG('L','I','N',' ')},       /* Lingala */
-  {"lo",        HB_TAG('L','A','O',' ')},       /* Lao */
-  {"lom",       HB_TAG('L','O','M',' ')},       /* Loma */
-  {"lrc",       HB_TAG('L','R','C',' ')},       /* Northern Luri */
-  {"lt",        HB_TAG('L','T','H',' ')},       /* Lithuanian */
-  {"lu",        HB_TAG('L','U','B',' ')},       /* Luba-Katanga */
-  {"lua",       HB_TAG('L','U','B',' ')},       /* Luba-Kasai */
-  {"luo",       HB_TAG('L','U','O',' ')},       /* Luo (Kenya and Tanzania) */
-  {"lus",       HB_TAG('M','I','Z',' ')},       /* Mizo */
-  {"luy",       HB_TAG('L','U','H',' ')},       /* Luyia/Oluluyia [macrolanguage] */
-  {"luz",       HB_TAG('L','R','C',' ')},       /* Southern Luri */
-  {"lv",        HB_TAG('L','V','I',' ')},       /* Latvian */
-  {"lzz",       HB_TAG('L','A','Z',' ')},       /* Laz */
-  {"mad",       HB_TAG('M','A','D',' ')},       /* Madurese */
-  {"mag",       HB_TAG('M','A','G',' ')},       /* Magahi */
-  {"mai",       HB_TAG('M','T','H',' ')},       /* Maithili */
-  {"mak",       HB_TAG('M','K','R',' ')},       /* Makasar */
-  {"mam",       HB_TAG('M','A','M',' ')},       /* Mam */
-  {"man",       HB_TAG('M','N','K',' ')},       /* Manding/Mandingo [macrolanguage] */
-  {"mdc",       HB_TAG('M','L','E',' ')},       /* Male (Papua New Guinea) */
-  {"mdf",       HB_TAG('M','O','K',' ')},       /* Moksha */
-  {"mdr",       HB_TAG('M','D','R',' ')},       /* Mandar */
-  {"mdy",       HB_TAG('M','L','E',' ')},       /* Male (Ethiopia) */
-  {"men",       HB_TAG('M','D','E',' ')},       /* Mende (Sierra Leone) */
-  {"mer",       HB_TAG('M','E','R',' ')},       /* Meru */
-  {"mfe",       HB_TAG('M','F','E',' ')},       /* Morisyen */
-  {"mg",        HB_TAG('M','L','G',' ')},       /* Malagasy [macrolanguage] */
-  {"mh",        HB_TAG('M','A','H',' ')},       /* Marshallese */
-  {"mhr",       HB_TAG('L','M','A',' ')},       /* Low Mari */
-  {"mi",        HB_TAG('M','R','I',' ')},       /* Maori */
-  {"min",       HB_TAG('M','I','N',' ')},       /* Minangkabau */
-  {"mk",        HB_TAG('M','K','D',' ')},       /* Macedonian */
-  {"mku",       HB_TAG('M','N','K',' ')},       /* Konyanka Maninka */
-  {"mkw",       HB_TAG('M','K','W',' ')},       /* Kituba (Congo) */
-  {"ml",        HB_TAG('M','L','R',' ')},       /* Malayalam */
-  {"mlq",       HB_TAG('M','N','K',' ')},       /* Western Maninkakan */
-  {"mn",        HB_TAG('M','N','G',' ')},       /* Mongolian [macrolanguage] */
-  {"mnc",       HB_TAG('M','C','H',' ')},       /* Manchu */
-  {"mni",       HB_TAG('M','N','I',' ')},       /* Manipuri */
-  {"mnk",       HB_TAG('M','N','D',' ')},       /* Mandinka */
-  {"mns",       HB_TAG('M','A','N',' ')},       /* Mansi */
-  {"mnw",       HB_TAG('M','O','N',' ')},       /* Mon */
-  {"mo",        HB_TAG('M','O','L',' ')},       /* Moldavian */
-  {"moh",       HB_TAG('M','O','H',' ')},       /* Mohawk */
-  {"mos",       HB_TAG('M','O','S',' ')},       /* Mossi */
-  {"mpe",       HB_TAG('M','A','J',' ')},       /* Majang */
-  {"mr",        HB_TAG('M','A','R',' ')},       /* Marathi */
-  {"mrh",       HB_TAG('Q','I','N',' ')},       /* Mara Chin */
-  {"mrj",       HB_TAG('H','M','A',' ')},       /* High Mari */
-  {"ms",        HB_TAG('M','L','Y',' ')},       /* Malay [macrolanguage] */
-  {"msc",       HB_TAG('M','N','K',' ')},       /* Sankaran Maninka */
-  {"mt",        HB_TAG('M','T','S',' ')},       /* Maltese */
-  {"mtr",       HB_TAG('M','A','W',' ')},       /* Mewari */
-  {"mus",       HB_TAG('M','U','S',' ')},       /* Creek */
-  {"mve",       HB_TAG('M','A','W',' ')},       /* Marwari (Pakistan) */
-  {"mwk",       HB_TAG('M','N','K',' ')},       /* Kita Maninkakan */
-  {"mwl",       HB_TAG('M','W','L',' ')},       /* Mirandese */
-  {"mwr",       HB_TAG('M','A','W',' ')},       /* Marwari [macrolanguage] */
-  {"mww",       HB_TAG('M','W','W',' ')},       /* Hmong Daw */
-  {"my",        HB_TAG('B','R','M',' ')},       /* Burmese */
-  {"mym",       HB_TAG('M','E','N',' ')},       /* Me'en */
-  {"myn",       HB_TAG('M','Y','N',' ')},       /* Mayan */
-  {"myq",       HB_TAG('M','N','K',' ')},       /* Forest Maninka (retired code) */
-  {"myv",       HB_TAG('E','R','Z',' ')},       /* Erzya */
-  {"mzn",       HB_TAG('M','Z','N',' ')},       /* Mazanderani */
-  {"na",        HB_TAG('N','A','U',' ')},       /* Nauru */
-  {"nag",       HB_TAG('N','A','G',' ')},       /* Naga-Assamese */
-  {"nah",       HB_TAG('N','A','H',' ')},       /* Nahuatl [family] */
-  {"nap",       HB_TAG('N','A','P',' ')},       /* Neapolitan */
-  {"nb",        HB_TAG('N','O','R',' ')},       /* Norwegian Bokmål */
-  {"nco",       HB_TAG('S','I','B',' ')},       /* Sibe */
-  {"nd",        HB_TAG('N','D','B',' ')},       /* [North] Ndebele */
-  {"ndc",       HB_TAG('N','D','C',' ')},       /* Ndau */
-  {"nds",       HB_TAG('N','D','S',' ')},       /* Low German/Low Saxon */
-  {"ne",        HB_TAG('N','E','P',' ')},       /* Nepali */
-  {"new",       HB_TAG('N','E','W',' ')},       /* Newari */
-  {"ng",        HB_TAG('N','D','G',' ')},       /* Ndonga */
-  {"nga",       HB_TAG('N','G','A',' ')},       /* Ngabaka */
-  {"ngl",       HB_TAG('L','M','W',' ')},       /* Lomwe */
-  {"ngo",       HB_TAG('S','X','T',' ')},       /* Sutu */
-  {"niu",       HB_TAG('N','I','U',' ')},       /* Niuean */
-  {"niv",       HB_TAG('G','I','L',' ')},       /* Gilyak */
-  {"nl",        HB_TAG('N','L','D',' ')},       /* Dutch */
-  {"nn",        HB_TAG('N','Y','N',' ')},       /* Norwegian Nynorsk */
-  {"no",        HB_TAG('N','O','R',' ')},       /* Norwegian [macrolanguage] */
-  {"nod",       HB_TAG('N','T','A',' ')},       /* Northern Thai */
-  {"noe",       HB_TAG('N','O','E',' ')},       /* Nimadi */
-  {"nog",       HB_TAG('N','O','G',' ')},       /* Nogai */
-  {"nov",       HB_TAG('N','O','V',' ')},       /* Novial */
-  {"nqo",       HB_TAG('N','K','O',' ')},       /* N'Ko */
-  {"nr",        HB_TAG('N','D','B',' ')},       /* [South] Ndebele */
-  {"nsk",       HB_TAG('N','A','S',' ')},       /* Naskapi */
-  {"nso",       HB_TAG('S','O','T',' ')},       /* [Northern] Sotho */
-  {"nv",        HB_TAG('N','A','V',' ')},       /* Navajo */
-  {"ny",        HB_TAG('C','H','I',' ')},       /* Chewa/Chichwa/Nyanja */
-  {"nym",       HB_TAG('N','Y','M',' ')},       /* Nyamwezi */
-  {"nyn",       HB_TAG('N','K','L',' ')},       /* Nyankole */
-  {"oc",        HB_TAG('O','C','I',' ')},       /* Occitan (post 1500) */
-  {"oj",        HB_TAG('O','J','B',' ')},       /* Ojibwa [macrolanguage] */
-  {"ojs",       HB_TAG('O','C','R',' ')},       /* Oji-Cree */
-  {"okm",       HB_TAG('K','O','H',' ')},       /* Korean Old Hangul */
-  {"om",        HB_TAG('O','R','O',' ')},       /* Oromo [macrolanguage] */
-  {"or",        HB_TAG('O','R','I',' ')},       /* Oriya */
-  {"os",        HB_TAG('O','S','S',' ')},       /* Ossetian */
-  {"pa",        HB_TAG('P','A','N',' ')},       /* Panjabi */
-  {"pag",       HB_TAG('P','A','G',' ')},       /* Pangasinan */
-  {"pam",       HB_TAG('P','A','M',' ')},       /* Kapampangan/Pampanga */
-  {"pap",       HB_TAG('P','A','P','0')},       /* Papiamento */
-  {"pau",       HB_TAG('P','A','U',' ')},       /* Palauan */
-  {"pcc",       HB_TAG('P','C','C',' ')},       /* Bouyei */
-  {"pcd",       HB_TAG('P','C','D',' ')},       /* Picard */
-  {"pce",       HB_TAG('P','L','G',' ')},       /* [Ruching] Palaung */
-  {"pck",       HB_TAG('Q','I','N',' ')},       /* Paite Chin */
-  {"pdc",       HB_TAG('P','D','C',' ')},       /* Pennsylvania German */
-  {"pes",       HB_TAG('F','A','R',' ')},       /* Iranian Persian */
-  {"phk",       HB_TAG('P','H','K',' ')},       /* Phake */
-  {"pi",        HB_TAG('P','A','L',' ')},       /* Pali */
-  {"pih",       HB_TAG('P','I','H',' ')},       /* Pitcairn-Norfolk */
-  {"pl",        HB_TAG('P','L','K',' ')},       /* Polish */
-  {"pll",       HB_TAG('P','L','G',' ')},       /* [Shwe] Palaung */
-  {"plp",       HB_TAG('P','A','P',' ')},       /* Palpa */
-  {"pms",       HB_TAG('P','M','S',' ')},       /* Piemontese */
-  {"pnb",       HB_TAG('P','N','B',' ')},       /* Western Panjabi */
-  {"poh",       HB_TAG('P','O','H',' ')},       /* Pocomchi */
-  {"pon",       HB_TAG('P','O','N',' ')},       /* Pohnpeian */
-  {"prs",       HB_TAG('D','R','I',' ')},       /* Afghan Persian/Dari */
-  {"ps",        HB_TAG('P','A','S',' ')},       /* Pashto/Pushto [macrolanguage] */
-  {"pt",        HB_TAG('P','T','G',' ')},       /* Portuguese */
-  {"pwo",       HB_TAG('P','W','O',' ')},       /* Pwo Western Karen */
-  {"qu",        HB_TAG('Q','U','Z',' ')},       /* Quechua [macrolanguage] */
-  {"quc",       HB_TAG('Q','U','C',' ')},       /* K'iche'/Quiché */
-  {"quh",       HB_TAG('Q','U','H',' ')},       /* Quechua (Bolivia) */
-  {"quz",       HB_TAG('Q','U','Z',' ')},       /* Cusco Quechua */
-  {"qvi",       HB_TAG('Q','V','I',' ')},       /* Quechua (Ecuador) */
-  {"qwh",       HB_TAG('Q','W','H',' ')},       /* Quechua (Peru) */
-  {"raj",       HB_TAG('R','A','J',' ')},       /* Rajasthani [macrolanguage] */
-  {"rar",       HB_TAG('R','A','R',' ')},       /* Rarotongan */
-  {"rbb",       HB_TAG('P','L','G',' ')},       /* Rumai Palaung */
-  {"rej",       HB_TAG('R','E','J',' ')},       /* Rejang */
-  {"ria",       HB_TAG('R','I','A',' ')},       /* Riang (India) */
-  {"rif",       HB_TAG('R','I','F',' ')},       /* Tarifit */
-  {"ril",       HB_TAG('R','I','A',' ')},       /* Riang (Myanmar) */
-  {"rit",       HB_TAG('R','I','T',' ')},       /* Ritarungo */
-  {"rki",       HB_TAG('A','R','K',' ')},       /* Rakhine */
-  {"rkw",       HB_TAG('R','K','W',' ')},       /* Arakwal */
-  {"rm",        HB_TAG('R','M','S',' ')},       /* Romansh */
-  {"rmy",       HB_TAG('R','M','Y',' ')},       /* Vlax Romani */
-  {"rn",        HB_TAG('R','U','N',' ')},       /* Rundi */
-  {"ro",        HB_TAG('R','O','M',' ')},       /* Romanian */
-  {"rom",       HB_TAG('R','O','Y',' ')},       /* Romany [macrolanguage] */
-  {"rtm",       HB_TAG('R','T','M',' ')},       /* Rotuman */
-  {"ru",        HB_TAG('R','U','S',' ')},       /* Russian */
-  {"rue",       HB_TAG('R','S','Y',' ')},       /* Rusyn */
-  {"rup",       HB_TAG('R','U','P',' ')},       /* Aromanian/Arumanian/Macedo-Romanian */
-  {"rw",        HB_TAG('R','U','A',' ')},       /* Kinyarwanda */
-  {"rwr",       HB_TAG('M','A','W',' ')},       /* Marwari (India) */
-  {"sa",        HB_TAG('S','A','N',' ')},       /* Sanskrit */
-  {"sah",       HB_TAG('Y','A','K',' ')},       /* Yakut */
-  {"sam",       HB_TAG('P','A','A',' ')},       /* Palestinian Aramaic */
-  {"sas",       HB_TAG('S','A','S',' ')},       /* Sasak */
-  {"sat",       HB_TAG('S','A','T',' ')},       /* Santali */
-  {"sc",        HB_TAG('S','R','D',' ')},       /* Sardinian [macrolanguage] */
-  {"sck",       HB_TAG('S','A','D',' ')},       /* Sadri */
-  {"scn",       HB_TAG('S','C','N',' ')},       /* Sicilian */
-  {"sco",       HB_TAG('S','C','O',' ')},       /* Scots */
-  {"scs",       HB_TAG('S','L','A',' ')},       /* [North] Slavey */
-  {"sd",        HB_TAG('S','N','D',' ')},       /* Sindhi */
-  {"se",        HB_TAG('N','S','M',' ')},       /* Northern Sami */
-  {"seh",       HB_TAG('S','N','A',' ')},       /* Sena */
-  {"sel",       HB_TAG('S','E','L',' ')},       /* Selkup */
-  {"sez",       HB_TAG('Q','I','N',' ')},       /* Senthang Chin */
-  {"sg",        HB_TAG('S','G','O',' ')},       /* Sango */
-  {"sga",       HB_TAG('S','G','A',' ')},       /* Old Irish (to 900) */
-  {"sgs",       HB_TAG('S','G','S',' ')},       /* Samogitian */
-  {"sgw",       HB_TAG('C','H','G',' ')},       /* Sebat Bet Gurage */
-/*{"sgw",       HB_TAG('S','G','W',' ')},*/     /* Sebat Bet Gurage (in SIL fonts) */
-  {"shi",       HB_TAG('S','H','I',' ')},       /* Tachelhit */
-  {"shn",       HB_TAG('S','H','N',' ')},       /* Shan */
-  {"si",        HB_TAG('S','N','H',' ')},       /* Sinhala */
-  {"sid",       HB_TAG('S','I','D',' ')},       /* Sidamo */
-  {"sjd",       HB_TAG('K','S','M',' ')},       /* Kildin Sami */
-  {"sk",        HB_TAG('S','K','Y',' ')},       /* Slovak */
-  {"skr",       HB_TAG('S','R','K',' ')},       /* Seraiki */
-  {"sl",        HB_TAG('S','L','V',' ')},       /* Slovenian */
-  {"sm",        HB_TAG('S','M','O',' ')},       /* Samoan */
-  {"sma",       HB_TAG('S','S','M',' ')},       /* Southern Sami */
-  {"smj",       HB_TAG('L','S','M',' ')},       /* Lule Sami */
-  {"smn",       HB_TAG('I','S','M',' ')},       /* Inari Sami */
-  {"sms",       HB_TAG('S','K','S',' ')},       /* Skolt Sami */
-  {"sn",        HB_TAG('S','N','A','0')},       /* Shona */
-  {"snk",       HB_TAG('S','N','K',' ')},       /* Soninke */
-  {"so",        HB_TAG('S','M','L',' ')},       /* Somali */
-  {"sop",       HB_TAG('S','O','P',' ')},       /* Songe */
-  {"sq",        HB_TAG('S','Q','I',' ')},       /* Albanian [macrolanguage] */
-  {"sr",        HB_TAG('S','R','B',' ')},       /* Serbian */
-  {"srr",       HB_TAG('S','R','R',' ')},       /* Serer */
-  {"ss",        HB_TAG('S','W','Z',' ')},       /* Swati */
-  {"st",        HB_TAG('S','O','T',' ')},       /* [Southern] Sotho */
-  {"stq",       HB_TAG('S','T','Q',' ')},       /* Saterfriesisch */
-  {"stv",       HB_TAG('S','I','G',' ')},       /* Silt'e */
-  {"su",        HB_TAG('S','U','N',' ')},       /* Sundanese */
-  {"suk",       HB_TAG('S','U','K',' ')},       /* Sukama */
-  {"suq",       HB_TAG('S','U','R',' ')},       /* Suri */
-  {"sv",        HB_TAG('S','V','E',' ')},       /* Swedish */
-  {"sva",       HB_TAG('S','V','A',' ')},       /* Svan */
-  {"sw",        HB_TAG('S','W','K',' ')},       /* Swahili [macrolanguage] */
-  {"swb",       HB_TAG('C','M','R',' ')},       /* Comorian */
-  {"swh",       HB_TAG('S','W','K',' ')},       /* Kiswahili/Swahili */
-  {"swv",       HB_TAG('M','A','W',' ')},       /* Shekhawati */
-  {"sxu",       HB_TAG('S','X','U',' ')},       /* Upper Saxon */
-  {"syc",       HB_TAG('S','Y','R',' ')},       /* Classical Syriac */
-  {"syl",       HB_TAG('S','Y','L',' ')},       /* Sylheti */
-  {"syr",       HB_TAG('S','Y','R',' ')},       /* Syriac [macrolanguage] */
-  {"szl",       HB_TAG('S','Z','L',' ')},       /* Silesian */
-  {"ta",        HB_TAG('T','A','M',' ')},       /* Tamil */
-  {"tab",       HB_TAG('T','A','B',' ')},       /* Tabasaran */
-  {"tcp",       HB_TAG('Q','I','N',' ')},       /* Tawr Chin */
-  {"tcy",       HB_TAG('T','U','L',' ')},       /* Tulu */
-  {"tcz",       HB_TAG('Q','I','N',' ')},       /* Thado Chin */
-  {"tdd",       HB_TAG('T','D','D',' ')},       /* Tai Nüa */
-  {"te",        HB_TAG('T','E','L',' ')},       /* Telugu */
-  {"tem",       HB_TAG('T','M','N',' ')},       /* Temne */
-  {"tet",       HB_TAG('T','E','T',' ')},       /* Tetum */
-  {"tg",        HB_TAG('T','A','J',' ')},       /* Tajik */
-  {"th",        HB_TAG('T','H','A',' ')},       /* Thai */
-  {"ti",        HB_TAG('T','G','Y',' ')},       /* Tigrinya */
-  {"tig",       HB_TAG('T','G','R',' ')},       /* Tigre */
-  {"tiv",       HB_TAG('T','I','V',' ')},       /* Tiv */
-  {"tk",        HB_TAG('T','K','M',' ')},       /* Turkmen */
-  {"tl",        HB_TAG('T','G','L',' ')},       /* Tagalog */
-  {"tmh",       HB_TAG('T','M','H',' ')},       /* Tamashek */
-  {"tn",        HB_TAG('T','N','A',' ')},       /* Tswana */
-  {"to",        HB_TAG('T','G','N',' ')},       /* Tonga (Tonga Islands) */
-  {"tod",       HB_TAG('T','O','D','0')},       /* Toma */
-  {"toi",       HB_TAG('T','N','G',' ')},       /* Tonga */
-  {"tpi",       HB_TAG('T','P','I',' ')},       /* Tok Pisin */
-  {"tr",        HB_TAG('T','R','K',' ')},       /* Turkish */
-  {"tru",       HB_TAG('T','U','A',' ')},       /* Turoyo Aramaic */
-  {"ts",        HB_TAG('T','S','G',' ')},       /* Tsonga */
-  {"tt",        HB_TAG('T','A','T',' ')},       /* Tatar */
-  {"tum",       HB_TAG('T','U','M',' ')},       /* Tumbuka */
-  {"tvl",       HB_TAG('T','V','L',' ')},       /* Tuvalu */
-  {"tw",        HB_TAG('T','W','I',' ')},       /* Twi */
-  {"ty",        HB_TAG('T','H','T',' ')},       /* Tahitian */
-  {"tyv",       HB_TAG('T','U','V',' ')},       /* Tuvin */
-  {"tyz",       HB_TAG('T','Y','Z',' ')},       /* Tày */
-  {"tzm",       HB_TAG('T','Z','M',' ')},       /* Central Atlas Tamazight */
-  {"tzo",       HB_TAG('T','Z','O',' ')},       /* Tzotzil */
-  {"udm",       HB_TAG('U','D','M',' ')},       /* Udmurt */
-  {"ug",        HB_TAG('U','Y','G',' ')},       /* Uighur */
-  {"uk",        HB_TAG('U','K','R',' ')},       /* Ukrainian */
-  {"umb",       HB_TAG('U','M','B',' ')},       /* Umbundu */
-  {"unr",       HB_TAG('M','U','N',' ')},       /* Mundari */
-  {"ur",        HB_TAG('U','R','D',' ')},       /* Urdu */
-  {"uz",        HB_TAG('U','Z','B',' ')},       /* Uzbek [macrolanguage] */
-  {"uzn",       HB_TAG('U','Z','B',' ')},       /* Northern Uzbek */
-  {"uzs",       HB_TAG('U','Z','B',' ')},       /* Southern Uzbek */
-  {"ve",        HB_TAG('V','E','N',' ')},       /* Venda */
-  {"vec",       HB_TAG('V','E','C',' ')},       /* Venetian */
-  {"vi",        HB_TAG('V','I','T',' ')},       /* Vietnamese */
-  {"vls",       HB_TAG('F','L','E',' ')},       /* Vlaams */
-  {"vmw",       HB_TAG('M','A','K',' ')},       /* Makhuwa */
-  {"vo",        HB_TAG('V','O','L',' ')},       /* Volapük */
-  {"vro",       HB_TAG('V','R','O',' ')},       /* Võro */
-  {"wa",        HB_TAG('W','L','N',' ')},       /* Walloon */
-  {"war",       HB_TAG('W','A','R',' ')},       /* Waray (Philippines) */
-  {"wbm",       HB_TAG('W','A',' ',' ')},       /* Wa */
-  {"wbr",       HB_TAG('W','A','G',' ')},       /* Wagdi */
-  {"wle",       HB_TAG('S','I','G',' ')},       /* Wolane */
-  {"wo",        HB_TAG('W','L','F',' ')},       /* Wolof */
-  {"wry",       HB_TAG('M','A','W',' ')},       /* Merwari */
-  {"wtm",       HB_TAG('W','T','M',' ')},       /* Mewati */
-  {"xal",       HB_TAG('K','L','M',' ')},       /* Kalmyk */
-  {"xan",       HB_TAG('S','E','K',' ')},       /* Sekota */
-  {"xh",        HB_TAG('X','H','S',' ')},       /* Xhosa */
-  {"xjb",       HB_TAG('X','J','B',' ')},       /* Minjangbal */
-  {"xog",       HB_TAG('X','O','G',' ')},       /* Soga */
-  {"xom",       HB_TAG('K','M','O',' ')},       /* Komo (Sudan) */
-  {"xpe",       HB_TAG('X','P','E',' ')},       /* Kpelle (Liberia) */
-  {"xsl",       HB_TAG('S','S','L',' ')},       /* South Slavey */
-  {"xst",       HB_TAG('S','I','G',' ')},       /* Silt'e (retired code) */
-  {"xwo",       HB_TAG('T','O','D',' ')},       /* Written Oirat (Todo) */
-  {"yao",       HB_TAG('Y','A','O',' ')},       /* Yao */
-  {"yap",       HB_TAG('Y','A','P',' ')},       /* Yapese */
-  {"yi",        HB_TAG('J','I','I',' ')},       /* Yiddish [macrolanguage] */
-  {"yo",        HB_TAG('Y','B','A',' ')},       /* Yoruba */
-  {"yos",       HB_TAG('Q','I','N',' ')},       /* Yos, deprecated by IANA in favor of Zou [zom] */
-  {"yso",       HB_TAG('N','I','S',' ')},       /* Nisi (China) */
-  {"za",        HB_TAG('Z','H','A',' ')},       /* Chuang/Zhuang [macrolanguage] */
-  {"zea",       HB_TAG('Z','E','A',' ')},       /* Zeeuws */
-  {"zgh",       HB_TAG('Z','G','H',' ')},       /* Standard Morrocan Tamazigh */
-  {"zne",       HB_TAG('Z','N','D',' ')},       /* Zande */
-  {"zom",       HB_TAG('Q','I','N',' ')},       /* Zou */
-  {"zu",        HB_TAG('Z','U','L',' ')},       /* Zulu */
-  {"zum",       HB_TAG('L','R','C',' ')},       /* Kumzari */
-  {"zza",       HB_TAG('Z','Z','A',' ')},       /* Zazaki */
-
-  /* The corresponding languages IDs for the following IDs are unclear,
-   * overlap, or are architecturally weird. Needs more research. */
-
-/*{"chp",       HB_TAG('S','A','Y',' ')},*/     /* Sayisi */
-/*{"cwd",       HB_TAG('T','C','R',' ')},*/     /* TH-Cree */
-/*{"emk",       HB_TAG('E','M','K',' ')},*/     /* Eastern Maninkakan */
-/*{"krc",       HB_TAG('B','A','L',' ')},*/     /* Balkar */
-/*{"??",        HB_TAG('B','C','R',' ')},*/     /* Bible Cree */
-/*{"zh?",       HB_TAG('C','H','N',' ')},*/     /* Chinese (seen in Microsoft fonts) */
-/*{"ar-Syrc?",  HB_TAG('G','A','R',' ')},*/     /* Garshuni */
-/*{"hy?",       HB_TAG('H','Y','E','0')},*/     /* Armenian East (ISO 639-3 hye according to Microsoft, but that’s equivalent to ISO 639-1 hy) */
-/*{"ga-Latg?/"  HB_TAG('I','R','T',' ')},*/     /* Irish Traditional */
-/*{"krc",       HB_TAG('K','A','R',' ')},*/     /* Karachay */
-/*{"ka-Geok?",  HB_TAG('K','G','E',' ')},*/     /* Khutsuri Georgian */
-/*{"kca",       HB_TAG('K','H','K',' ')},*/     /* Khanty-Kazim */
-/*{"kca",       HB_TAG('K','H','S',' ')},*/     /* Khanty-Shurishkar */
-/*{"kca",       HB_TAG('K','H','V',' ')},*/     /* Khanty-Vakhi */
-/*{"kqs, kss",  HB_TAG('K','I','S',' ')},*/     /* Kisii */
-/*{"lua",       HB_TAG('L','U','A',' ')},*/     /* Luba-Lulua */
-/*{"mlq",       HB_TAG('M','L','N',' ')},*/     /* Malinke */
-/*{"nso",       HB_TAG('N','S','O',' ')},*/     /* Sotho, Northern */
-/*{"??",        HB_TAG('M','A','L',' ')},*/     /* Malayalam Traditional */
-/*{"csw",       HB_TAG('N','C','R',' ')},*/     /* N-Cree */
-/*{"csw",       HB_TAG('N','H','C',' ')},*/     /* Norway House Cree */
-/*{"el-polyton",        HB_TAG('P','G','R',' ')},*/     /* Polytonic Greek */
-/*{"bgr, cnh, cnw, czt, sez, tcp, csy, ctd, flm, pck, tcz, zom, cmr, dao, hlt, cka, cnk, mrh, mwg, cbl, cnb, csh",      HB_TAG('Q','I','N',' ')},*/     /* Chin */
-/*{"??",        HB_TAG('Y','I','C',' ')},*/     /* Yi Classic */
-/*{"zh-Latn-pinyin",    HB_TAG('Z','H','P',' ')},*/     /* Chinese Phonetic */
-};
-
-typedef struct {
-  char language[11];
-  hb_tag_t tag;
-} LangTagLong;
-static const LangTagLong ot_languages_zh[] = {
-  /* Store longest-first, if one is a prefix of another. */
-  {"zh-cn",     HB_TAG('Z','H','S',' ')},       /* Chinese (China) */
-  {"zh-hk",     HB_TAG('Z','H','H',' ')},       /* Chinese (Hong Kong) */
-  {"zh-mo",     HB_TAG('Z','H','H',' ')},       /* Chinese (Macao) */
-  {"zh-sg",     HB_TAG('Z','H','S',' ')},       /* Chinese (Singapore) */
-  {"zh-tw",     HB_TAG('Z','H','T',' ')},       /* Chinese (Taiwan) */
-  {"zh-hans",   HB_TAG('Z','H','S',' ')},       /* Chinese (Simplified) */
-  {"zh-hant-hk",HB_TAG('Z','H','H',' ')},       /* Chinese (Hong Kong) */
-  {"zh-hant-mo",HB_TAG('Z','H','H',' ')},       /* Chinese (Macao) */
-  {"zh-hant",   HB_TAG('Z','H','T',' ')},       /* Chinese (Traditional) */
-};
-
 static int
 lang_compare_first_component (const void *pa,
                               const void *pb)
@@ -895,6 +189,21 @@
   return strncmp (a, b, MAX (da, db));
 }
 
+static bool
+subtag_matches (const char *lang_str,
+                const char *limit,
+                const char *subtag)
+{
+  do {
+    const char *s = strstr (lang_str, subtag);
+    if (!s || s >= limit)
+      return false;
+    if (!ISALNUM (s[strlen (subtag)]))
+      return true;
+    lang_str = s + strlen (subtag);
+  } while (true);
+}
+
 static hb_bool_t
 lang_matches (const char *lang_str, const char *spec)
 {
@@ -904,106 +213,186 @@
          (lang_str[len] == '\0' || lang_str[len] == '-');
 }
 
+typedef struct {
+  char language[4];
+  hb_tag_t tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
+} LangTag;
+
+#include "hb-ot-tag-table.hh"
+
+/* The corresponding languages IDs for the following IDs are unclear,
+ * overlap, or are architecturally weird. Needs more research. */
+
+/*{"??",        {HB_TAG('B','C','R',' ')}},*/   /* Bible Cree */
+/*{"zh?",       {HB_TAG('C','H','N',' ')}},*/   /* Chinese (seen in Microsoft fonts) */
+/*{"ar-Syrc?",  {HB_TAG('G','A','R',' ')}},*/   /* Garshuni */
+/*{"??",        {HB_TAG('N','G','R',' ')}},*/   /* Nagari */
+/*{"??",        {HB_TAG('Y','I','C',' ')}},*/   /* Yi Classic */
+/*{"zh?",       {HB_TAG('Z','H','P',' ')}},*/   /* Chinese Phonetic */
+
 hb_tag_t
 hb_ot_tag_from_language (hb_language_t language)
 {
-  const char *lang_str, *s;
-
-  if (language == HB_LANGUAGE_INVALID)
-    return HB_OT_TAG_DEFAULT_LANGUAGE;
-
-  lang_str = hb_language_to_string (language);
-
-  s = strstr (lang_str, "x-hbot");
-  if (s) {
-    char tag[4];
-    int i;
-    s += 6;
-    for (i = 0; i < 4 && ISALNUM (s[i]); i++)
-      tag[i] = TOUPPER (s[i]);
-    if (i) {
-      for (; i < 4; i++)
-        tag[i] = ' ';
-      return HB_TAG (tag[0], tag[1], tag[2], tag[3]);
-    }
-  }
-
-  /*
-   * "fonipa" is a variant tag in BCP-47, meaning the International Phonetic Alphabet.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-fonipa")) {
-    return HB_TAG('I','P','P','H');  /* Phonetic transcription—IPA conventions */
-  }
+  unsigned int count = 1;
+  hb_tag_t tags[1];
+  hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
+  return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE;
+}
 
-  /*
-   * "fonnapa" is a variant tag in BCP-47, meaning the North American Phonetic Alphabet
-   * also known as Americanist Phonetic Notation.  It can be applied to any language.
-   */
-  if (strstr (lang_str, "-fonnapa")) {
-    return HB_TAG('A','P','P','H');  /* Phonetic transcription—Americanist conventions */
-  }
-
-  /*
-   * "Syre" is a BCP-47 script tag, meaning the Estrangela variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syre")) {
-    return HB_TAG('S','Y','R','E');  /* Estrangela Syriac */
-  }
+static void
+hb_ot_tags_from_language (const char   *lang_str,
+                          const char   *limit,
+                          unsigned int *count,
+                          hb_tag_t     *tags)
+{
+  const char *s;
 
-  /*
-   * "Syrj" is a BCP-47 script tag, meaning the Western variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrj")) {
-    return HB_TAG('S','Y','R','J');  /* Western Syriac */
-  }
+  /* Check for matches of multiple subtags. */
+  if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags))
+    return;
 
-  /*
-   * "Syrn" is a BCP-47 script tag, meaning the Eastern variant of the Syriac script.
-   * It can be applied to any language.
-   */
-  if (strstr (lang_str, "-syrn")) {
-    return HB_TAG('S','Y','R','N');  /* Eastern Syriac */
-  }
-
-  /* Find a language matching in the first component */
+  /* Find a language matching in the first component. */
+  s = strchr (lang_str, '-');
   {
     const LangTag *lang_tag;
+    if (s && limit - lang_str >= 6)
+    {
+      const char *extlang_end = strchr (s + 1, '-');
+      /* If there is an extended language tag, use it. */
+      if (3 == (extlang_end ? extlang_end - s - 1 : strlen (s + 1)) &&
+          ISALPHA (s[1]))
+        lang_str = s + 1;
+    }
     lang_tag = (LangTag *) bsearch (lang_str, ot_languages,
                                     ARRAY_LENGTH (ot_languages), sizeof (LangTag),
                                     lang_compare_first_component);
     if (lang_tag)
-      return lang_tag->tag;
+    {
+      unsigned int i;
+      for (i = 0; i < *count && lang_tag->tags[i] != HB_TAG_NONE; i++)
+        tags[i] = lang_tag->tags[i];
+      *count = i;
+      return;
+    }
   }
 
-  /* Otherwise, check the Chinese ones */
-  if (0 == lang_compare_first_component (lang_str, "zh"))
-  {
-    unsigned int i;
-
-    for (i = 0; i < ARRAY_LENGTH (ot_languages_zh); i++)
-    {
-      const LangTagLong *lang_tag;
-      lang_tag = &ot_languages_zh[i];
-      if (lang_matches (lang_str, lang_tag->language))
-        return lang_tag->tag;
-    }
-
-    /* Otherwise just return 'ZHS ' */
-    return HB_TAG('Z','H','S',' ');
-  }
-
-  s = strchr (lang_str, '-');
   if (!s)
     s = lang_str + strlen (lang_str);
   if (s - lang_str == 3) {
     /* Assume it's ISO-639-3 and upper-case and use it. */
-    return hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
+    tags[0] = hb_tag_from_string (lang_str, s - lang_str) & ~0x20202000u;
+    *count = 1;
+    return;
   }
 
-  return HB_OT_TAG_DEFAULT_LANGUAGE;
+  *count = 0;
+}
+
+static bool
+parse_private_use_subtag (const char     *private_use_subtag,
+                          unsigned int   *count,
+                          hb_tag_t       *tags,
+                          const char     *prefix,
+                          unsigned char (*normalize) (unsigned char))
+{
+  if (private_use_subtag && count && tags && *count)
+  {
+    const char *s = strstr (private_use_subtag, prefix);
+    if (s)
+    {
+      char tag[4];
+      int i;
+      s += strlen (prefix);
+      for (i = 0; i < 4 && ISALNUM (s[i]); i++)
+        tag[i] = normalize (s[i]);
+      if (i)
+      {
+        for (; i < 4; i++)
+          tag[i] = ' ';
+        tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
+        if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
+          tags[0] ^= ~0xDFDFDFDF;
+        *count = 1;
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+/**
+ * hb_ot_tags_from_script_and_language:
+ * @script: an #hb_script_t to convert.
+ * @language: an #hb_language_t to convert.
+ * @script_count: (allow-none): maximum number of script tags to retrieve (IN)
+ * and actual number of script tags retrieved (OUT)
+ * @script_tags: (out) (allow-none): array of size at least @script_count to store the
+ * script tag results
+ * @language_count: (allow-none): maximum number of language tags to retrieve
+ * (IN) and actual number of language tags retrieved (OUT)
+ * @language_tags: (out) (allow-none): array of size at least @language_count to store
+ * the language tag results
+ *
+ * Converts an #hb_script_t and an #hb_language_t to script and language tags.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_ot_tags_from_script_and_language (hb_script_t   script,
+                                     hb_language_t language,
+                                     unsigned int *script_count /* IN/OUT */,
+                                     hb_tag_t     *script_tags /* OUT */,
+                                     unsigned int *language_count /* IN/OUT */,
+                                     hb_tag_t     *language_tags /* OUT */)
+{
+  bool needs_script = true;
+
+  if (language == HB_LANGUAGE_INVALID)
+  {
+    if (language_count && language_tags && *language_count)
+      *language_count = 0;
+  }
+  else
+  {
+    const char *lang_str, *s, *limit, *private_use_subtag;
+    bool needs_language;
+
+    lang_str = hb_language_to_string (language);
+    limit = nullptr;
+    private_use_subtag = nullptr;
+    if (lang_str[0] == 'x' && lang_str[1] == '-')
+    {
+      private_use_subtag = lang_str;
+    } else {
+      for (s = lang_str + 1; *s; s++)
+      {
+        if (s[-1] == '-' && s[1] == '-')
+        {
+          if (s[0] == 'x')
+          {
+            private_use_subtag = s;
+            if (!limit)
+              limit = s - 1;
+            break;
+          } else if (!limit)
+          {
+            limit = s - 1;
+          }
+        }
+      }
+      if (!limit)
+        limit = s;
+    }
+
+    needs_script = parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER);
+    needs_language = parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER);
+
+    if (needs_language && language_count && language_tags && *language_count)
+      hb_ot_tags_from_language (lang_str, limit, language_count, language_tags);
+  }
+
+  if (needs_script && script_count && script_tags && *script_count)
+    hb_ot_all_tags_from_script (script, script_count, script_tags);
 }
 
 /**
@@ -1023,36 +412,16 @@
   if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
     return nullptr;
 
-  /* struct LangTag has only room for 3-letter language tags. */
-  switch (tag) {
-  case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
-    return hb_language_from_string ("und-fonnapa", -1);
-  case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
-    return hb_language_from_string ("und-fonipa", -1);
-  case HB_TAG('S','Y','R',' '):  /* Syriac [macrolanguage] */
-    return hb_language_from_string ("syr", -1);
-  case HB_TAG('S','Y','R','E'):  /* Estrangela Syriac */
-    return hb_language_from_string ("und-Syre", -1);
-  case HB_TAG('S','Y','R','J'):  /* Western Syriac */
-    return hb_language_from_string ("und-Syrj", -1);
-  case HB_TAG('S','Y','R','N'):  /* Eastern Syriac */
-    return hb_language_from_string ("und-Syrn", -1);
+  {
+    hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag);
+    if (disambiguated_tag != HB_LANGUAGE_INVALID)
+      return disambiguated_tag;
   }
 
   for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
-    if (ot_languages[i].tag == tag)
+    if (ot_languages[i].tags[0] == tag)
       return hb_language_from_string (ot_languages[i].language, -1);
 
-  /* If tag starts with ZH, it's Chinese */
-  if ((tag & 0xFFFF0000u)  == 0x5A480000u) {
-    switch (tag) {
-      case HB_TAG('Z','H','H',' '): return hb_language_from_string ("zh-hk", -1); /* Hong Kong */
-      case HB_TAG('Z','H','S',' '): return hb_language_from_string ("zh-Hans", -1); /* Simplified */
-      case HB_TAG('Z','H','T',' '): return hb_language_from_string ("zh-Hant", -1); /* Traditional */
-      default: break; /* Fall through */
-    }
-  }
-
   /* Else return a custom language in the form of "x-hbotABCD" */
   {
     unsigned char buf[11] = "x-hbot";
@@ -1067,9 +436,74 @@
   }
 }
 
+/**
+ * hb_ot_tags_to_script_and_language:
+ * @script_tag: a script tag
+ * @language_tag: a language tag
+ * @script: (allow-none): the #hb_script_t corresponding to @script_tag (OUT).
+ * @language: (allow-none): the #hb_language_t corresponding to @script_tag and
+ * @language_tag (OUT).
+ *
+ * Converts a script tag and a language tag to an #hb_script_t and an
+ * #hb_language_t.
+ *
+ * Since: 2.0.0
+ **/
+void
+hb_ot_tags_to_script_and_language (hb_tag_t       script_tag,
+                                   hb_tag_t       language_tag,
+                                   hb_script_t   *script /* OUT */,
+                                   hb_language_t *language /* OUT */)
+{
+  hb_script_t script_out = hb_ot_tag_to_script (script_tag);
+  if (script)
+    *script = script_out;
+  if (language)
+  {
+    unsigned int script_count = 1;
+    hb_tag_t primary_script_tag[1];
+    hb_ot_tags_from_script_and_language (script_out,
+                                         HB_LANGUAGE_INVALID,
+                                         &script_count,
+                                         primary_script_tag,
+                                         nullptr, nullptr);
+    *language = hb_ot_tag_to_language (language_tag);
+    if (script_count == 0 || primary_script_tag[0] != script_tag)
+    {
+      unsigned char *buf;
+      const char *lang_str = hb_language_to_string (*language);
+      size_t len = strlen (lang_str);
+      buf = (unsigned char *) malloc (len + 11);
+      if (unlikely (!buf))
+      {
+        *language = nullptr;
+      }
+      else
+      {
+        memcpy (buf, lang_str, len);
+        if (lang_str[0] != 'x' || lang_str[1] != '-') {
+          buf[len++] = '-';
+          buf[len++] = 'x';
+        }
+        buf[len++] = '-';
+        buf[len++] = 'h';
+        buf[len++] = 'b';
+        buf[len++] = 's';
+        buf[len++] = 'c';
+        buf[len++] = script_tag >> 24;
+        buf[len++] = (script_tag >> 16) & 0xFF;
+        buf[len++] = (script_tag >> 8) & 0xFF;
+        buf[len++] = script_tag & 0xFF;
+        *language = hb_language_from_string ((char *) buf, len);
+        free (buf);
+      }
+    }
+  }
+}
+
 #ifdef MAIN
 static inline void
-test_langs_sorted (void)
+test_langs_sorted ()
 {
   for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
   {
@@ -1084,7 +518,7 @@
 }
 
 int
-main (void)
+main ()
 {
   test_langs_sorted ();
   return 0;
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-tag.h	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_H_IN
-#error "Include <hb-ot.h> instead."
-#endif
-
-#ifndef HB_OT_TAG_H
-#define HB_OT_TAG_H
-
-#include "hb.h"
-
-HB_BEGIN_DECLS
-
-
-#define HB_OT_TAG_DEFAULT_SCRIPT        HB_TAG ('D', 'F', 'L', 'T')
-#define HB_OT_TAG_DEFAULT_LANGUAGE      HB_TAG ('d', 'f', 'l', 't')
-
-HB_EXTERN void
-hb_ot_tags_from_script (hb_script_t  script,
-                        hb_tag_t    *script_tag_1,
-                        hb_tag_t    *script_tag_2);
-
-HB_EXTERN hb_script_t
-hb_ot_tag_to_script (hb_tag_t tag);
-
-HB_EXTERN hb_tag_t
-hb_ot_tag_from_language (hb_language_t language);
-
-HB_EXTERN hb_language_t
-hb_ot_tag_to_language (hb_tag_t tag);
-
-
-HB_END_DECLS
-
-#endif /* HB_OT_TAG_H */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-avar-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-avar-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_AVAR_TABLE_HH
 #define HB_OT_VAR_AVAR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * avar -- Axis Variations
@@ -42,7 +42,7 @@
 
 struct AxisValueMap
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -59,7 +59,7 @@
 
 struct SegmentMaps : ArrayOf<AxisValueMap>
 {
-  inline int map (int value) const
+  int map (int value) const
   {
     /* The following special-cases are not part of OpenType, which requires
      * that at least -1, 0, and +1 must be mapped. But we include these as
@@ -93,14 +93,15 @@
             (value - arrayZ[i-1].fromCoord) + denom/2) / denom;
   }
 
-  DEFINE_SIZE_ARRAY (2, arrayZ);
+  public:
+  DEFINE_SIZE_ARRAY (2, *this);
 };
 
 struct avar
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_avar;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (unlikely (!(version.sanitize (c) &&
@@ -108,7 +109,7 @@
                     c->check_struct (this))))
       return_trace (false);
 
-    const SegmentMaps *map = axisSegmentMapsZ;
+    const SegmentMaps *map = &firstAxisSegmentMaps;
     unsigned int count = axisCount;
     for (unsigned int i = 0; i < count; i++)
     {
@@ -120,11 +121,11 @@
     return_trace (true);
   }
 
-  inline void map_coords (int *coords, unsigned int coords_length) const
+  void map_coords (int *coords, unsigned int coords_length) const
   {
     unsigned int count = MIN<unsigned int> (coords_length, axisCount);
 
-    const SegmentMaps *map = axisSegmentMapsZ;
+    const SegmentMaps *map = &firstAxisSegmentMaps;
     for (unsigned int i = 0; i < count; i++)
     {
       coords[i] = map->map (coords[i]);
@@ -139,7 +140,7 @@
   HBUINT16      axisCount;      /* The number of variation axes in the font. This
                                  * must be the same number as axisCount in the
                                  * 'fvar' table. */
-  SegmentMaps   axisSegmentMapsZ[VAR];
+  SegmentMaps   firstAxisSegmentMaps;
 
   public:
   DEFINE_SIZE_MIN (8);
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-fvar-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-fvar-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_FVAR_TABLE_HH
 #define HB_OT_VAR_FVAR_TABLE_HH
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
 /*
  * fvar -- Font Variations
@@ -42,29 +42,40 @@
 
 struct InstanceRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
+  friend struct fvar;
+
+  hb_array_t<const Fixed> get_coordinates (unsigned int axis_count) const
+  { return coordinatesZ.as_array (axis_count); }
+
+  bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  c->check_array (coordinates, coordinates[0].static_size, axis_count));
+                  c->check_array (coordinatesZ.arrayZ, axis_count));
   }
 
   protected:
   NameID        subfamilyNameID;/* The name ID for entries in the 'name' table
                                  * that provide subfamily names for this instance. */
-  HBUINT16      reserved;       /* Reserved for future use — set to 0. */
-  Fixed         coordinates[VAR];/* The coordinates array for this instance. */
+  HBUINT16      flags;          /* Reserved for future use — set to 0. */
+  UnsizedArrayOf<Fixed>
+                coordinatesZ;   /* The coordinates array for this instance. */
   //NameID      postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
   //                              * table that provide PostScript names for this
   //                              * instance. */
 
   public:
-  DEFINE_SIZE_ARRAY (4, coordinates);
+  DEFINE_SIZE_UNBOUNDED (4);
 };
 
 struct AxisRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  enum
+  {
+    AXIS_FLAG_HIDDEN    = 0x0001,
+  };
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -75,7 +86,7 @@
   Fixed         minValue;       /* The minimum coordinate value for the axis. */
   Fixed         defaultValue;   /* The default coordinate value for the axis. */
   Fixed         maxValue;       /* The maximum coordinate value for the axis. */
-  HBUINT16      reserved;       /* Reserved for future use — set to 0. */
+  HBUINT16      flags;          /* Axis flags. */
   NameID        axisNameID;     /* The name ID for entries in the 'name' table that
                                  * provide a display name for this axis. */
 
@@ -85,50 +96,80 @@
 
 struct fvar
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_fvar;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_fvar;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool has_data () const { return version.to_int (); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
                   likely (version.major == 1) &&
                   c->check_struct (this) &&
+                  axisSize == 20 && /* Assumed in our code. */
                   instanceSize >= axisCount * 4 + 4 &&
-                  axisSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-                  instanceSize <= 1024 && /* Arbitrary, just to simplify overflow checks. */
-                  c->check_range (this, things) &&
-                  c->check_range (&StructAtOffset<char> (this, things),
-                                  axisCount * axisSize + instanceCount * instanceSize));
+                  get_axes ().sanitize (c) &&
+                  c->check_range (get_instance (0), instanceCount, instanceSize));
   }
 
-  inline unsigned int get_axis_count (void) const
-  { return axisCount; }
-
-  inline bool get_axis (unsigned int index, hb_ot_var_axis_t *info) const
-  {
-    if (unlikely (index >= axisCount))
-      return false;
+  unsigned int get_axis_count () const { return axisCount; }
 
-    if (info)
-    {
-      const AxisRecord &axis = get_axes ()[index];
-      info->tag = axis.axisTag;
-      info->name_id =  axis.axisNameID;
-      info->default_value = axis.defaultValue / 65536.;
-      /* Ensure order, to simplify client math. */
-      info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
-      info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
-    }
-
-    return true;
+  void get_axis_deprecated (unsigned int axis_index,
+                                   hb_ot_var_axis_t *info) const
+  {
+    const AxisRecord &axis = get_axes ()[axis_index];
+    info->tag = axis.axisTag;
+    info->name_id =  axis.axisNameID;
+    info->default_value = axis.defaultValue / 65536.;
+    /* Ensure order, to simplify client math. */
+    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
+    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
   }
 
-  inline unsigned int get_axis_infos (unsigned int      start_offset,
-                                      unsigned int     *axes_count /* IN/OUT */,
-                                      hb_ot_var_axis_t *axes_array /* OUT */) const
+  void get_axis_info (unsigned int axis_index,
+                      hb_ot_var_axis_info_t *info) const
+  {
+    const AxisRecord &axis = get_axes ()[axis_index];
+    info->axis_index = axis_index;
+    info->tag = axis.axisTag;
+    info->name_id =  axis.axisNameID;
+    info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
+    info->default_value = axis.defaultValue / 65536.;
+    /* Ensure order, to simplify client math. */
+    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
+    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
+    info->reserved = 0;
+  }
+
+  unsigned int get_axes_deprecated (unsigned int      start_offset,
+                                    unsigned int     *axes_count /* IN/OUT */,
+                                    hb_ot_var_axis_t *axes_array /* OUT */) const
   {
     if (axes_count)
     {
+      /* TODO Rewrite as hb_array_t<>::sub-array() */
+      unsigned int count = axisCount;
+      start_offset = MIN (start_offset, count);
+
+      count -= start_offset;
+      axes_array += start_offset;
+
+      count = MIN (count, *axes_count);
+      *axes_count = count;
+
+      for (unsigned int i = 0; i < count; i++)
+        get_axis_deprecated (start_offset + i, axes_array + i);
+    }
+    return axisCount;
+  }
+
+  unsigned int get_axis_infos (unsigned int           start_offset,
+                               unsigned int          *axes_count /* IN/OUT */,
+                               hb_ot_var_axis_info_t *axes_array /* OUT */) const
+  {
+    if (axes_count)
+    {
+      /* TODO Rewrite as hb_array_t<>::sub-array() */
       unsigned int count = axisCount;
       start_offset = MIN (start_offset, count);
 
@@ -139,32 +180,48 @@
       *axes_count = count;
 
       for (unsigned int i = 0; i < count; i++)
-        get_axis (start_offset + i, axes_array + i);
+        get_axis_info (start_offset + i, axes_array + i);
     }
     return axisCount;
   }
 
-  inline bool find_axis (hb_tag_t tag, unsigned int *index, hb_ot_var_axis_t *info) const
+  bool find_axis_deprecated (hb_tag_t tag,
+                             unsigned int *axis_index,
+                             hb_ot_var_axis_t *info) const
   {
     const AxisRecord *axes = get_axes ();
     unsigned int count = get_axis_count ();
     for (unsigned int i = 0; i < count; i++)
       if (axes[i].axisTag == tag)
       {
-        if (index)
-          *index = i;
-        return get_axis (i, info);
+        if (axis_index)
+          *axis_index = i;
+        get_axis_deprecated (i, info);
+        return true;
       }
-    if (index)
-      *index = HB_OT_VAR_NO_AXIS_INDEX;
+    if (axis_index)
+      *axis_index = HB_OT_VAR_NO_AXIS_INDEX;
     return false;
   }
 
-  inline int normalize_axis_value (unsigned int axis_index, float v) const
+  bool find_axis_info (hb_tag_t tag,
+                       hb_ot_var_axis_info_t *info) const
   {
-    hb_ot_var_axis_t axis;
-    if (!get_axis (axis_index, &axis))
-      return 0;
+    const AxisRecord *axes = get_axes ();
+    unsigned int count = get_axis_count ();
+    for (unsigned int i = 0; i < count; i++)
+      if (axes[i].axisTag == tag)
+      {
+        get_axis_info (i, info);
+        return true;
+      }
+    return false;
+  }
+
+  int normalize_axis_value (unsigned int axis_index, float v) const
+  {
+    hb_ot_var_axis_info_t axis;
+    get_axis_info (axis_index, &axis);
 
     v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
 
@@ -174,20 +231,65 @@
       v = (v - axis.default_value) / (axis.default_value - axis.min_value);
     else
       v = (v - axis.default_value) / (axis.max_value - axis.default_value);
-    return (int) (v * 16384. + (v >= 0. ? .5 : -.5));
+    return (int) (v * 16384.f + (v >= 0.f ? .5f : -.5f));
+  }
+
+  unsigned int get_instance_count () const { return instanceCount; }
+
+  hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int instance_index) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
+    return instance->subfamilyNameID;
+  }
+
+  hb_ot_name_id_t get_instance_postscript_name_id (unsigned int instance_index) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
+    if (instanceSize >= axisCount * 4 + 6)
+      return StructAfter<NameID> (instance->get_coordinates (axisCount));
+    return HB_OT_NAME_ID_INVALID;
+  }
+
+  unsigned int get_instance_coords (unsigned int  instance_index,
+                                           unsigned int *coords_length, /* IN/OUT */
+                                           float        *coords         /* OUT */) const
+  {
+    const InstanceRecord *instance = get_instance (instance_index);
+    if (unlikely (!instance))
+    {
+      if (coords_length)
+        *coords_length = 0;
+      return 0;
+    }
+
+    if (coords_length && *coords_length)
+    {
+      hb_array_t<const Fixed> instanceCoords = instance->get_coordinates (axisCount)
+                                                         .sub_array (0, *coords_length);
+      for (unsigned int i = 0; i < instanceCoords.length; i++)
+        coords[i] = instanceCoords.arrayZ[i].to_float ();
+    }
+    return axisCount;
   }
 
   protected:
-  inline const AxisRecord * get_axes (void) const
-  { return &StructAtOffset<AxisRecord> (this, things); }
+  hb_array_t<const AxisRecord> get_axes () const
+  { return hb_array (&(this+firstAxis), axisCount); }
 
-  inline const InstanceRecord * get_instances (void) const
-  { return &StructAtOffset<InstanceRecord> (get_axes () + axisCount, 0); }
+  const InstanceRecord *get_instance (unsigned int i) const
+  {
+    if (unlikely (i >= instanceCount)) return nullptr;
+   return &StructAtOffset<InstanceRecord> (&StructAfter<InstanceRecord> (get_axes ()),
+                                           i * instanceSize);
+  }
 
   protected:
   FixedVersion<>version;        /* Version of the fvar table
                                  * initially set to 0x00010000u */
-  Offset16      things;         /* Offset in bytes from the beginning of the table
+  OffsetTo<AxisRecord>
+                firstAxis;      /* Offset in bytes from the beginning of the table
                                  * to the start of the AxisRecord array. */
   HBUINT16      reserved;       /* This field is permanently reserved. Set to 2. */
   HBUINT16      axisCount;      /* The number of variation axes in the font (the
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-hvar-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-hvar-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_HVAR_TABLE_HH
 #define HB_OT_VAR_HVAR_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
 
 namespace OT {
@@ -35,11 +35,13 @@
 
 struct DeltaSetIndexMap
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-                  c->check_array (mapData, get_width (), mapCount));
+                  c->check_range (mapDataZ.arrayZ,
+                                  mapCount,
+                                  get_width ()));
   }
 
   unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */
@@ -55,7 +57,7 @@
     unsigned int u = 0;
     { /* Fetch it. */
       unsigned int w = get_width ();
-      const HBUINT8 *p = mapData + w * v;
+      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
       for (; w; w--)
         u = (u << 8) + *p++;
     }
@@ -71,20 +73,19 @@
   }
 
   protected:
-  inline unsigned int get_width (void) const
-  { return ((format >> 4) & 3) + 1; }
+  unsigned int get_width () const          { return ((format >> 4) & 3) + 1; }
 
-  inline unsigned int get_inner_bitcount (void) const
-  { return (format & 0xF) + 1; }
+  unsigned int get_inner_bitcount () const { return (format & 0xF) + 1; }
 
   protected:
   HBUINT16      format;         /* A packed field that describes the compressed
                                  * representation of delta-set indices. */
   HBUINT16      mapCount;       /* The number of mapping entries. */
-  HBUINT8               mapData[VAR];   /* The delta-set index mapping data. */
+  UnsizedArrayOf<HBUINT8>
+                mapDataZ;       /* The delta-set index mapping data. */
 
   public:
-  DEFINE_SIZE_ARRAY (4, mapData);
+  DEFINE_SIZE_ARRAY (4, mapDataZ);
 };
 
 
@@ -99,10 +100,10 @@
 
 struct HVARVVAR
 {
-  static const hb_tag_t HVARTag = HB_OT_TAG_HVAR;
-  static const hb_tag_t VVARTag = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t HVARTag = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t VVARTag = HB_OT_TAG_VVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
@@ -113,15 +114,14 @@
                   rsbMap.sanitize (c, this));
   }
 
-  inline float get_advance_var (hb_codepoint_t glyph,
-                                int *coords, unsigned int coord_count) const
+  float get_advance_var (hb_codepoint_t glyph,
+                         const int *coords, unsigned int coord_count) const
   {
     unsigned int varidx = (this+advMap).map (glyph);
     return (this+varStore).get_delta (varidx, coords, coord_count);
   }
 
-  inline bool has_sidebearing_deltas (void) const
-  { return lsbMap && rsbMap; }
+  bool has_sidebearing_deltas () const { return lsbMap && rsbMap; }
 
   protected:
   FixedVersion<>version;        /* Version of the metrics variation table
@@ -140,12 +140,12 @@
 };
 
 struct HVAR : HVARVVAR {
-  static const hb_tag_t tableTag        = HB_OT_TAG_HVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_HVAR;
 };
 struct VVAR : HVARVVAR {
-  static const hb_tag_t tableTag        = HB_OT_TAG_VVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_VVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (static_cast<const HVARVVAR *> (this)->sanitize (c) &&
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-mvar-table.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var-mvar-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,7 +27,7 @@
 #ifndef HB_OT_VAR_MVAR_TABLE_HH
 #define HB_OT_VAR_MVAR_TABLE_HH
 
-#include "hb-ot-layout-common-private.hh"
+#include "hb-ot-layout-common.hh"
 
 
 namespace OT {
@@ -35,7 +35,7 @@
 
 struct VariationValueRecord
 {
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this));
@@ -58,9 +58,9 @@
 
 struct MVAR
 {
-  static const hb_tag_t tableTag        = HB_OT_TAG_MVAR;
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_MVAR;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (version.sanitize (c) &&
@@ -68,14 +68,16 @@
                   c->check_struct (this) &&
                   valueRecordSize >= VariationValueRecord::static_size &&
                   varStore.sanitize (c, this) &&
-                  c->check_array (values, valueRecordSize, valueRecordCount));
+                  c->check_range (valuesZ.arrayZ,
+                                  valueRecordCount,
+                                  valueRecordSize));
   }
 
-  inline float get_var (hb_tag_t tag,
-                        int *coords, unsigned int coord_count) const
+  float get_var (hb_tag_t tag,
+                 const int *coords, unsigned int coord_count) const
   {
     const VariationValueRecord *record;
-    record = (VariationValueRecord *) bsearch (&tag, values,
+    record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ,
                                                valueRecordCount, valueRecordSize,
                                                tag_compare);
     if (!record)
@@ -85,7 +87,7 @@
   }
 
 protected:
-  static inline int tag_compare (const void *pa, const void *pb)
+  static int tag_compare (const void *pa, const void *pb)
   {
     const hb_tag_t *a = (const hb_tag_t *) pa;
     const Tag *b = (const Tag *) pb;
@@ -101,11 +103,12 @@
   HBUINT16      valueRecordCount;/* The number of value records — may be zero. */
   OffsetTo<VariationStore>
                 varStore;       /* Offset to item variation store table. */
-  HBUINT8               values[VAR];    /* Array of value records. The records must be
+  UnsizedArrayOf<HBUINT8>
+                valuesZ;        /* Array of value records. The records must be
                                  * in binary order of their valueTag field. */
 
   public:
-  DEFINE_SIZE_ARRAY (12, values);
+  DEFINE_SIZE_ARRAY (12, valuesZ);
 };
 
 } /* namespace OT */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,39 +24,35 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
 
-#include "hb-ot-layout-private.hh"
+#include "hb-ot-face.hh"
 #include "hb-ot-var-avar-table.hh"
 #include "hb-ot-var-fvar-table.hh"
 #include "hb-ot-var-mvar-table.hh"
 #include "hb-ot-var.h"
 
+
+/**
+ * SECTION:hb-ot-var
+ * @title: hb-ot-var
+ * @short_description: OpenType Font Variations
+ * @include: hb-ot.h
+ *
+ * Functions for fetching information about OpenType Variable Fonts.
+ **/
+
+
 /*
  * fvar/avar
  */
 
-static inline const OT::fvar&
-_get_fvar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::fvar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->fvar.get ());
-}
-static inline const OT::avar&
-_get_avar (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::avar);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->avar.get ());
-}
 
 /**
  * hb_ot_var_has_data:
  * @face: #hb_face_t to test
  *
  * This function allows to verify the presence of OpenType variation data on the face.
- * Alternatively, use hb_ot_var_get_axis_count().
  *
  * Return value: true if face has a `fvar' table and false otherwise
  *
@@ -65,7 +61,7 @@
 hb_bool_t
 hb_ot_var_has_data (hb_face_t *face)
 {
-  return &_get_fvar (face) != &Null(OT::fvar);
+  return face->table.fvar->has_data ();
 }
 
 /**
@@ -76,14 +72,14 @@
 unsigned int
 hb_ot_var_get_axis_count (hb_face_t *face)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_count ();
+  return face->table.fvar->get_axis_count ();
 }
 
 /**
  * hb_ot_var_get_axes:
  *
  * Since: 1.4.2
+ * Deprecated: 2.2.0
  **/
 unsigned int
 hb_ot_var_get_axes (hb_face_t        *face,
@@ -91,14 +87,14 @@
                     unsigned int     *axes_count /* IN/OUT */,
                     hb_ot_var_axis_t *axes_array /* OUT */)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.get_axis_infos (start_offset, axes_count, axes_array);
+  return face->table.fvar->get_axes_deprecated (start_offset, axes_count, axes_array);
 }
 
 /**
  * hb_ot_var_find_axis:
  *
  * Since: 1.4.2
+ * Deprecated: 2.2.0
  **/
 hb_bool_t
 hb_ot_var_find_axis (hb_face_t        *face,
@@ -106,8 +102,68 @@
                      unsigned int     *axis_index,
                      hb_ot_var_axis_t *axis_info)
 {
-  const OT::fvar &fvar = _get_fvar (face);
-  return fvar.find_axis (axis_tag, axis_index, axis_info);
+  return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info);
+}
+
+/**
+ * hb_ot_var_get_axis_infos:
+ *
+ * Since: 2.2.0
+ **/
+HB_EXTERN unsigned int
+hb_ot_var_get_axis_infos (hb_face_t             *face,
+                          unsigned int           start_offset,
+                          unsigned int          *axes_count /* IN/OUT */,
+                          hb_ot_var_axis_info_t *axes_array /* OUT */)
+{
+  return face->table.fvar->get_axis_infos (start_offset, axes_count, axes_array);
+}
+
+/**
+ * hb_ot_var_find_axis_info:
+ *
+ * Since: 2.2.0
+ **/
+HB_EXTERN hb_bool_t
+hb_ot_var_find_axis_info (hb_face_t             *face,
+                          hb_tag_t               axis_tag,
+                          hb_ot_var_axis_info_t *axis_info)
+{
+  return face->table.fvar->find_axis_info (axis_tag, axis_info);
+}
+
+
+/*
+ * Named instances.
+ */
+
+unsigned int
+hb_ot_var_get_named_instance_count (hb_face_t *face)
+{
+  return face->table.fvar->get_instance_count ();
+}
+
+hb_ot_name_id_t
+hb_ot_var_named_instance_get_subfamily_name_id (hb_face_t   *face,
+                                                unsigned int instance_index)
+{
+  return face->table.fvar->get_instance_subfamily_name_id (instance_index);
+}
+
+hb_ot_name_id_t
+hb_ot_var_named_instance_get_postscript_name_id (hb_face_t  *face,
+                                                unsigned int instance_index)
+{
+  return face->table.fvar->get_instance_postscript_name_id (instance_index);
+}
+
+unsigned int
+hb_ot_var_named_instance_get_design_coords (hb_face_t    *face,
+                                            unsigned int  instance_index,
+                                            unsigned int *coords_length, /* IN/OUT */
+                                            float        *coords         /* OUT */)
+{
+  return face->table.fvar->get_instance_coords (instance_index, coords_length, coords);
 }
 
 
@@ -126,17 +182,16 @@
   for (unsigned int i = 0; i < coords_length; i++)
     coords[i] = 0;
 
-  const OT::fvar &fvar = _get_fvar (face);
+  const OT::fvar &fvar = *face->table.fvar;
   for (unsigned int i = 0; i < variations_length; i++)
   {
-    unsigned int axis_index;
-    if (hb_ot_var_find_axis (face, variations[i].tag, &axis_index, nullptr) &&
-        axis_index < coords_length)
-      coords[axis_index] = fvar.normalize_axis_value (axis_index, variations[i].value);
+    hb_ot_var_axis_info_t info;
+    if (hb_ot_var_find_axis_info (face, variations[i].tag, &info) &&
+        info.axis_index < coords_length)
+      coords[info.axis_index] = fvar.normalize_axis_value (info.axis_index, variations[i].value);
   }
 
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (coords, coords_length);
+  face->table.avar->map_coords (coords, coords_length);
 }
 
 /**
@@ -150,10 +205,9 @@
                             const float *design_coords, /* IN */
                             int *normalized_coords /* OUT */)
 {
-  const OT::fvar &fvar = _get_fvar (face);
+  const OT::fvar &fvar = *face->table.fvar;
   for (unsigned int i = 0; i < coords_length; i++)
     normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
 
-  const OT::avar &avar = _get_avar (face);
-  avar.map_coords (normalized_coords, coords_length);
+  face->table.avar->map_coords (normalized_coords, coords_length);
 }
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-var.h	Tue Mar 26 09:05:10 2019 -0400
@@ -47,44 +47,85 @@
  * fvar / avar
  */
 
-/**
- * hb_ot_var_axis_t:
- *
- * Since: 1.4.2
- */
-typedef struct hb_ot_var_axis_t {
-  hb_tag_t tag;
-  unsigned int name_id;
-  float min_value;
-  float default_value;
-  float max_value;
-} hb_ot_var_axis_t;
-
 HB_EXTERN hb_bool_t
 hb_ot_var_has_data (hb_face_t *face);
 
-/**
- * HB_OT_VAR_NO_AXIS_INDEX:
- *
- * Since: 1.4.2
+
+/*
+ * Variation axes.
  */
-#define HB_OT_VAR_NO_AXIS_INDEX         0xFFFFFFFFu
+
 
 HB_EXTERN unsigned int
 hb_ot_var_get_axis_count (hb_face_t *face);
 
+/**
+ * hb_ot_var_axis_flags_t:
+ * @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces.
+ *
+ * Since: 2.2.0
+ */
+typedef enum { /*< flags >*/
+  HB_OT_VAR_AXIS_FLAG_HIDDEN    = 0x00000001u,
+
+  _HB_OT_VAR_AXIS_FLAG_MAX_VALUE= 0x7FFFFFFFu /*< skip >*/
+} hb_ot_var_axis_flags_t;
+
+/**
+ * hb_ot_var_axis_info_t:
+ *
+ * Since: 2.2.0
+ */
+typedef struct hb_ot_var_axis_info_t
+{
+  unsigned int                  axis_index;
+  hb_tag_t                      tag;
+  hb_ot_name_id_t               name_id;
+  hb_ot_var_axis_flags_t        flags;
+  float                         min_value;
+  float                         default_value;
+  float                         max_value;
+  /*< private >*/
+  unsigned int                  reserved;
+} hb_ot_var_axis_info_t;
+
 HB_EXTERN unsigned int
-hb_ot_var_get_axes (hb_face_t        *face,
-                    unsigned int      start_offset,
-                    unsigned int     *axes_count /* IN/OUT */,
-                    hb_ot_var_axis_t *axes_array /* OUT */);
+hb_ot_var_get_axis_infos (hb_face_t             *face,
+                          unsigned int           start_offset,
+                          unsigned int          *axes_count /* IN/OUT */,
+                          hb_ot_var_axis_info_t *axes_array /* OUT */);
 
 HB_EXTERN hb_bool_t
-hb_ot_var_find_axis (hb_face_t        *face,
-                     hb_tag_t          axis_tag,
-                     unsigned int     *axis_index,
-                     hb_ot_var_axis_t *axis_info);
+hb_ot_var_find_axis_info (hb_face_t             *face,
+                          hb_tag_t               axis_tag,
+                          hb_ot_var_axis_info_t *axis_info);
+
+
+/*
+ * Named instances.
+ */
+
+HB_EXTERN unsigned int
+hb_ot_var_get_named_instance_count (hb_face_t *face);
 
+HB_EXTERN hb_ot_name_id_t
+hb_ot_var_named_instance_get_subfamily_name_id (hb_face_t   *face,
+                                                unsigned int instance_index);
+
+HB_EXTERN hb_ot_name_id_t
+hb_ot_var_named_instance_get_postscript_name_id (hb_face_t  *face,
+                                                unsigned int instance_index);
+
+HB_EXTERN unsigned int
+hb_ot_var_named_instance_get_design_coords (hb_face_t    *face,
+                                            unsigned int  instance_index,
+                                            unsigned int *coords_length, /* IN/OUT */
+                                            float        *coords         /* OUT */);
+
+
+/*
+ * Conversions.
+ */
 
 HB_EXTERN void
 hb_ot_var_normalize_variations (hb_face_t            *face,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-vorg-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,181 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_OT_VORG_TABLE_HH
+#define HB_OT_VORG_TABLE_HH
+
+#include "hb-open-type.hh"
+
+/*
+ * VORG -- Vertical Origin Table
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/vorg
+ */
+#define HB_OT_TAG_VORG HB_TAG('V','O','R','G')
+
+namespace OT {
+
+struct VertOriginMetric
+{
+  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
+  public:
+  GlyphID       glyph;
+  FWORD         vertOriginY;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct VORG
+{
+  static constexpr hb_tag_t tableTag = HB_OT_TAG_VORG;
+
+  bool has_data () const { return version.to_int (); }
+
+  int get_y_origin (hb_codepoint_t glyph) const
+  {
+    unsigned int i;
+    if (!vertYOrigins.bfind (glyph, &i))
+      return defaultVertOriginY;
+    return vertYOrigins[i].vertOriginY;
+  }
+
+  bool _subset (const hb_subset_plan_t *plan HB_UNUSED,
+                const VORG *vorg_table,
+                const hb_vector_t<VertOriginMetric> &subset_metrics,
+                unsigned int dest_sz,
+                void *dest) const
+  {
+    hb_serialize_context_t c (dest, dest_sz);
+
+    VORG *subset_table = c.start_serialize<VORG> ();
+    if (unlikely (!c.extend_min (*subset_table)))
+      return false;
+
+    subset_table->version.major.set (1);
+    subset_table->version.minor.set (0);
+
+    subset_table->defaultVertOriginY.set (vorg_table->defaultVertOriginY);
+    subset_table->vertYOrigins.len.set (subset_metrics.length);
+
+    bool success = true;
+    if (subset_metrics.length > 0)
+    {
+      unsigned int  size = VertOriginMetric::static_size * subset_metrics.length;
+      VertOriginMetric  *metrics = c.allocate_size<VertOriginMetric> (size);
+      if (likely (metrics != nullptr))
+        memcpy (metrics, &subset_metrics[0], size);
+      else
+        success = false;
+    }
+    c.end_serialize ();
+
+    return success;
+  }
+
+  bool subset (hb_subset_plan_t *plan) const
+  {
+    hb_blob_t *vorg_blob = hb_sanitize_context_t().reference_table<VORG> (plan->source);
+    const VORG *vorg_table = vorg_blob->as<VORG> ();
+
+    /* count the number of glyphs to be included in the subset table */
+    hb_vector_t<VertOriginMetric> subset_metrics;
+    subset_metrics.init ();
+    unsigned int glyph = 0;
+    unsigned int i = 0;
+    while ((glyph < plan->glyphs.length) && (i < vertYOrigins.len))
+    {
+      if (plan->glyphs[glyph] > vertYOrigins[i].glyph)
+        i++;
+      else if (plan->glyphs[glyph] < vertYOrigins[i].glyph)
+        glyph++;
+      else
+      {
+        VertOriginMetric *metrics = subset_metrics.push ();
+        metrics->glyph.set (glyph);
+        metrics->vertOriginY.set (vertYOrigins[i].vertOriginY);
+        glyph++;
+        i++;
+      }
+    }
+
+    /* alloc the new table */
+    unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.length;
+    void *dest = (void *) malloc (dest_sz);
+    if (unlikely (!dest))
+    {
+      subset_metrics.fini ();
+      hb_blob_destroy (vorg_blob);
+      return false;
+    }
+
+    /* serialize the new table */
+    if (!_subset (plan, vorg_table, subset_metrics, dest_sz, dest))
+    {
+      subset_metrics.fini ();
+      free (dest);
+      hb_blob_destroy (vorg_blob);
+      return false;
+    }
+
+    hb_blob_t *result = hb_blob_create ((const char *)dest,
+                                        dest_sz,
+                                        HB_MEMORY_MODE_READONLY,
+                                        dest,
+                                        free);
+    bool success = plan->add_table (HB_OT_TAG_VORG, result);
+    hb_blob_destroy (result);
+    subset_metrics.fini ();
+    hb_blob_destroy (vorg_blob);
+    return success;
+  }
+
+  bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+                  version.major == 1 &&
+                  vertYOrigins.sanitize (c));
+  }
+
+  protected:
+  FixedVersion<>        version;                /* Version of VORG table. Set to 0x00010000u. */
+  FWORD                 defaultVertOriginY;     /* The default vertical origin. */
+  SortedArrayOf<VertOriginMetric>
+                        vertYOrigins;           /* The array of vertical origins. */
+
+  public:
+  DEFINE_SIZE_ARRAY(8, vertYOrigins);
+};
+} /* namespace OT */
+
+#endif /* HB_OT_VORG_TABLE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot.h	Tue Mar 26 09:05:10 2019 -0400
@@ -30,10 +30,12 @@
 
 #include "hb.h"
 
+#include "hb-ot-color.h"
+#include "hb-ot-deprecated.h"
 #include "hb-ot-font.h"
 #include "hb-ot-layout.h"
 #include "hb-ot-math.h"
-#include "hb-ot-tag.h"
+#include "hb-ot-name.h"
 #include "hb-ot-shape.h"
 #include "hb-ot-var.h"
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1242 +0,0 @@
-/*
- * Copyright © 2007,2008,2009  Red Hat, Inc.
- * Copyright © 2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_PRIVATE_HH
-#define HB_PRIVATE_HH
-
-#define _GNU_SOURCE 1
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "hb.h"
-#define HB_H_IN
-#ifdef HAVE_OT
-#include "hb-ot.h"
-#define HB_OT_H_IN
-#endif
-
-#include <math.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-#include <intrin.h>
-#endif
-
-#define HB_PASTE1(a,b) a##b
-#define HB_PASTE(a,b) HB_PASTE1(a,b)
-
-/* Compile-time custom allocator support. */
-
-#if defined(hb_malloc_impl) \
- && defined(hb_calloc_impl) \
- && defined(hb_realloc_impl) \
- && defined(hb_free_impl)
-extern "C" void* hb_malloc_impl(size_t size);
-extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
-extern "C" void* hb_realloc_impl(void *ptr, size_t size);
-extern "C" void  hb_free_impl(void *ptr);
-#define malloc hb_malloc_impl
-#define calloc hb_calloc_impl
-#define realloc hb_realloc_impl
-#define free hb_free_impl
-#endif
-
-
-/* Compiler attributes */
-
-
-#if __cplusplus < 201103L
-
-#ifndef nullptr
-#define nullptr NULL
-#endif
-
-// Static assertions
-#ifndef static_assert
-#define static_assert(e, msg) \
-        HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
-#endif // static_assert
-
-#ifdef __GNUC__
-#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
-#define thread_local __thread
-#endif
-#else
-#define thread_local
-#endif
-
-#endif // __cplusplus < 201103L
-
-#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
-#define likely(expr) (__builtin_expect (!!(expr), 1))
-#define unlikely(expr) (__builtin_expect (!!(expr), 0))
-#else
-#define likely(expr) (expr)
-#define unlikely(expr) (expr)
-#endif
-
-#if !defined(__GNUC__) && !defined(__clang__)
-#undef __attribute__
-#define __attribute__(x)
-#endif
-
-#if __GNUC__ >= 3
-#define HB_PURE_FUNC    __attribute__((pure))
-#define HB_CONST_FUNC   __attribute__((const))
-#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
-#else
-#define HB_PURE_FUNC
-#define HB_CONST_FUNC
-#define HB_PRINTF_FUNC(format_idx, arg_idx)
-#endif
-#if __GNUC__ >= 4
-#define HB_UNUSED       __attribute__((unused))
-#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
-#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
-#else
-#define HB_UNUSED
-#endif
-
-#ifndef HB_INTERNAL
-# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
-#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
-# else
-#  define HB_INTERNAL
-#  define HB_NO_VISIBILITY 1
-# endif
-#endif
-
-#if __GNUC__ >= 3
-#define HB_FUNC __PRETTY_FUNCTION__
-#elif defined(_MSC_VER)
-#define HB_FUNC __FUNCSIG__
-#else
-#define HB_FUNC __func__
-#endif
-
-#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140)
-/* https://github.com/harfbuzz/harfbuzz/issues/630 */
-#define __restrict
-#endif
-
-/*
- * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
- * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
- * cases that fall through without a break or return statement. HB_FALLTHROUGH
- * is only needed on cases that have code:
- *
- * switch (foo) {
- *   case 1: // These cases have no code. No fallthrough annotations are needed.
- *   case 2:
- *   case 3:
- *     foo = 4; // This case has code, so a fallthrough annotation is needed:
- *     HB_FALLTHROUGH;
- *   default:
- *     return foo;
- * }
- */
-#if defined(__clang__) && __cplusplus >= 201103L
-   /* clang's fallthrough annotations are only available starting in C++11. */
-#  define HB_FALLTHROUGH [[clang::fallthrough]]
-#elif __GNUC__ >= 7
-   /* GNU fallthrough attribute is available from GCC7 */
-#  define HB_FALLTHROUGH __attribute__((fallthrough))
-#elif defined(_MSC_VER)
-   /*
-    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
-    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
-    */
-#  include <sal.h>
-#  define HB_FALLTHROUGH __fallthrough
-#else
-#  define HB_FALLTHROUGH /* FALLTHROUGH */
-#endif
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-   /* We need Windows Vista for both Uniscribe backend and for
-    * MemoryBarrier.  We don't support compiling on Windows XP,
-    * though we run on it fine. */
-#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
-#    undef _WIN32_WINNT
-#  endif
-#  ifndef _WIN32_WINNT
-#    define _WIN32_WINNT 0x0600
-#  endif
-#  ifndef WIN32_LEAN_AND_MEAN
-#    define WIN32_LEAN_AND_MEAN 1
-#  endif
-#  ifndef STRICT
-#    define STRICT 1
-#  endif
-
-#  if defined(_WIN32_WCE)
-     /* Some things not defined on Windows CE. */
-#    define vsnprintf _vsnprintf
-#    define getenv(Name) nullptr
-#    if _WIN32_WCE < 0x800
-#      define setlocale(Category, Locale) "C"
-static int errno = 0; /* Use something better? */
-#    endif
-#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
-#    define getenv(Name) nullptr
-#  endif
-#  if defined(_MSC_VER) && _MSC_VER < 1900
-#    define snprintf _snprintf
-#  endif
-#endif
-
-#if HAVE_ATEXIT
-/* atexit() is only safe to be called from shared libraries on certain
- * platforms.  Whitelist.
- * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
-#  if defined(__linux) && defined(__GLIBC_PREREQ)
-#    if __GLIBC_PREREQ(2,3)
-/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
-#      define HB_USE_ATEXIT 1
-#    endif
-#  elif defined(_MSC_VER) || defined(__MINGW32__)
-/* For MSVC:
- * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
- * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
- * mingw32 headers say atexit is safe to use in shared libraries.
- */
-#    define HB_USE_ATEXIT 1
-#  elif defined(__ANDROID__)
-/* This is available since Android NKD r8 or r8b:
- * https://issuetracker.google.com/code/p/android/issues/detail?id=6455
- */
-#    define HB_USE_ATEXIT 1
-#  elif defined(__APPLE__)
-/* For macOS and related platforms, the atexit man page indicates
- * that it will be invoked when the library is unloaded, not only
- * at application exit.
- */
-#    define HB_USE_ATEXIT 1
-#  endif
-#endif
-#ifdef HB_NO_ATEXIT
-#  undef HB_USE_ATEXIT
-#endif
-
-/* Basics */
-
-#undef MIN
-template <typename Type>
-static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
-
-#undef MAX
-template <typename Type>
-static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
-
-static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
-{ return (a + (b - 1)) / b; }
-
-
-#undef  ARRAY_LENGTH
-template <typename Type, unsigned int n>
-static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
-/* A const version, but does not detect erratically being called on pointers. */
-#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
-
-#define HB_STMT_START do
-#define HB_STMT_END   while (0)
-
-template <unsigned int cond> class hb_assert_constant_t;
-template <> class hb_assert_constant_t<1> {};
-
-#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
-
-/* Lets assert int types.  Saves trouble down the road. */
-
-static_assert ((sizeof (int8_t) == 1), "");
-static_assert ((sizeof (uint8_t) == 1), "");
-static_assert ((sizeof (int16_t) == 2), "");
-static_assert ((sizeof (uint16_t) == 2), "");
-static_assert ((sizeof (int32_t) == 4), "");
-static_assert ((sizeof (uint32_t) == 4), "");
-static_assert ((sizeof (int64_t) == 8), "");
-static_assert ((sizeof (uint64_t) == 8), "");
-
-static_assert ((sizeof (hb_codepoint_t) == 4), "");
-static_assert ((sizeof (hb_position_t) == 4), "");
-static_assert ((sizeof (hb_mask_t) == 4), "");
-static_assert ((sizeof (hb_var_int_t) == 4), "");
-
-
-/* We like our types POD */
-
-#define _ASSERT_TYPE_POD1(_line, _type) union _type_##_type##_on_line_##_line##_is_not_POD { _type instance; }
-#define _ASSERT_TYPE_POD0(_line, _type) _ASSERT_TYPE_POD1 (_line, _type)
-#define ASSERT_TYPE_POD(_type)          _ASSERT_TYPE_POD0 (__LINE__, _type)
-
-#ifdef __GNUC__
-# define _ASSERT_INSTANCE_POD1(_line, _instance) \
-        HB_STMT_START { \
-                typedef __typeof__(_instance) _type_##_line; \
-                _ASSERT_TYPE_POD1 (_line, _type_##_line); \
-        } HB_STMT_END
-#else
-# define _ASSERT_INSTANCE_POD1(_line, _instance)        typedef int _assertion_on_line_##_line##_not_tested
-#endif
-# define _ASSERT_INSTANCE_POD0(_line, _instance)        _ASSERT_INSTANCE_POD1 (_line, _instance)
-# define ASSERT_INSTANCE_POD(_instance)                 _ASSERT_INSTANCE_POD0 (__LINE__, _instance)
-
-/* Check _assertion in a method environment */
-#define _ASSERT_POD1(_line) \
-        HB_UNUSED inline void _static_assertion_on_line_##_line (void) const \
-        { _ASSERT_INSTANCE_POD1 (_line, *this); /* Make sure it's POD. */ }
-# define _ASSERT_POD0(_line)    _ASSERT_POD1 (_line)
-# define ASSERT_POD()           _ASSERT_POD0 (__LINE__)
-
-
-
-/* Tiny functions */
-
-/*
- * Void!
- */
-typedef const struct _hb_void_t *hb_void_t;
-#define HB_VOID ((const _hb_void_t *) nullptr)
-
-/* Return the number of 1 bits in v. */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_popcount (T v)
-{
-#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return __builtin_popcount (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return __builtin_popcountl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return __builtin_popcountll (v);
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "HACKMEM 169" */
-    uint32_t y;
-    y = (v >> 1) &033333333333;
-    y = v - y - ((y >>1) & 033333333333);
-    return (((y + (y >> 3)) & 030707070707) % 077);
-  }
-
-  if (sizeof (T) == 8)
-  {
-    unsigned int shift = 32;
-    return _hb_popcount<uint32_t> ((uint32_t) v) + _hb_popcount ((uint32_t) (v >> shift));
-  }
-
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return _hb_popcount<uint64_t> ((uint64_t) v) + _hb_popcount ((uint64_t) (v >> shift));
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-/* Returns the number of bits needed to store number */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_bit_storage (T v)
-{
-  if (unlikely (!v)) return 0;
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return sizeof (unsigned int) * 8 - __builtin_clz (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
-#endif
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-  if (sizeof (T) <= sizeof (unsigned int))
-  {
-    unsigned long where;
-    _BitScanReverse (&where, v);
-    return 1 + where;
-  }
-# if _WIN64
-  if (sizeof (T) <= 8)
-  {
-    unsigned long where;
-    _BitScanReverse64 (&where, v);
-    return 1 + where;
-  }
-# endif
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "bithacks" */
-    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
-    const unsigned int S[] = {1, 2, 4, 8, 16};
-    unsigned int r = 0;
-    for (int i = 4; i >= 0; i--)
-      if (v & b[i])
-      {
-        v >>= S[i];
-        r |= S[i];
-      }
-    return r + 1;
-  }
-  if (sizeof (T) <= 8)
-  {
-    /* "bithacks" */
-    const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
-    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
-    unsigned int r = 0;
-    for (int i = 5; i >= 0; i--)
-      if (v & b[i])
-      {
-        v >>= S[i];
-        r |= S[i];
-      }
-    return r + 1;
-  }
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return (v >> shift) ? _hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
-                          _hb_bit_storage<uint64_t> ((uint64_t) v);
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-/* Returns the number of zero bits in the least significant side of v */
-template <typename T>
-static inline HB_CONST_FUNC unsigned int
-_hb_ctz (T v)
-{
-  if (unlikely (!v)) return 0;
-
-#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  if (sizeof (T) <= sizeof (unsigned int))
-    return __builtin_ctz (v);
-
-  if (sizeof (T) <= sizeof (unsigned long))
-    return __builtin_ctzl (v);
-
-  if (sizeof (T) <= sizeof (unsigned long long))
-    return __builtin_ctzll (v);
-#endif
-
-#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-  if (sizeof (T) <= sizeof (unsigned int))
-  {
-    unsigned long where;
-    _BitScanForward (&where, v);
-    return where;
-  }
-# if _WIN64
-  if (sizeof (T) <= 8)
-  {
-    unsigned long where;
-    _BitScanForward64 (&where, v);
-    return where;
-  }
-# endif
-#endif
-
-  if (sizeof (T) <= 4)
-  {
-    /* "bithacks" */
-    unsigned int c = 32;
-    v &= - (int32_t) v;
-    if (v) c--;
-    if (v & 0x0000FFFF) c -= 16;
-    if (v & 0x00FF00FF) c -= 8;
-    if (v & 0x0F0F0F0F) c -= 4;
-    if (v & 0x33333333) c -= 2;
-    if (v & 0x55555555) c -= 1;
-    return c;
-  }
-  if (sizeof (T) <= 8)
-  {
-    /* "bithacks" */
-    unsigned int c = 64;
-    v &= - (int64_t) (v);
-    if (v) c--;
-    if (v & 0x00000000FFFFFFFFULL) c -= 32;
-    if (v & 0x0000FFFF0000FFFFULL) c -= 16;
-    if (v & 0x00FF00FF00FF00FFULL) c -= 8;
-    if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
-    if (v & 0x3333333333333333ULL) c -= 2;
-    if (v & 0x5555555555555555ULL) c -= 1;
-    return c;
-  }
-  if (sizeof (T) == 16)
-  {
-    unsigned int shift = 64;
-    return (uint64_t) v ? _hb_bit_storage<uint64_t> ((uint64_t) v) :
-                          _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift;
-  }
-
-  assert (0);
-  return 0; /* Shut up stupid compiler. */
-}
-
-static inline bool
-_hb_unsigned_int_mul_overflows (unsigned int count, unsigned int size)
-{
-  return (size > 0) && (count >= ((unsigned int) -1) / size);
-}
-
-static inline unsigned int
-_hb_ceil_to_4 (unsigned int v)
-{
-  return ((v - 1) | 3) + 1;
-}
-
-
-
-/*
- *
- * Utility types
- *
- */
-
-#define HB_DISALLOW_COPY_AND_ASSIGN(TypeName) \
-  TypeName(const TypeName&); \
-  void operator=(const TypeName&)
-
-/*
- * Static pools
- */
-
-/* Global nul-content Null pool.  Enlarge as necessary. */
-
-#define HB_NULL_POOL_SIZE 264
-static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
-
-#ifdef HB_NO_VISIBILITY
-static
-#else
-extern HB_INTERNAL
-#endif
-void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-/* Generic nul-content Null objects. */
-template <typename Type>
-static inline Type const & Null (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  return *reinterpret_cast<Type const *> (_hb_NullPool);
-}
-#define Null(Type) Null<Type>()
-
-/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
-#define DEFINE_NULL_DATA(Namespace, Type, data) \
-} /* Close namespace. */ \
-static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \
-template <> \
-/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
-  return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \
-} \
-namespace Namespace { \
-/* The following line really exists such that we end in a place needing semicolon */ \
-static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small.  Enlarge.")
-
-
-/* Global writable pool.  Enlarge as necessary. */
-
-/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
- * for correct operation. It only exist to catch and divert program logic bugs instead of
- * causing bad memory access. So, races there are not actually introducing incorrectness
- * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
-#ifdef HB_NO_VISIBILITY
-static
-#else
-extern HB_INTERNAL
-#endif
-/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)]
-#ifdef HB_NO_VISIBILITY
-= {}
-#endif
-;
-/* CRAP pool: Common Region for Access Protection. */
-template <typename Type>
-static inline Type& Crap (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
-  *obj = Null(Type);
-  return *obj;
-}
-#define Crap(Type) Crap<Type>()
-
-template <typename Type>
-struct CrapOrNull {
-  static inline Type & get (void) { return Crap(Type); }
-};
-template <typename Type>
-struct CrapOrNull<const Type> {
-  static inline Type const & get (void) { return Null(Type); }
-};
-#define CrapOrNull(Type) CrapOrNull<Type>::get ()
-
-
-
-/* arrays and maps */
-
-
-#define HB_PREALLOCED_ARRAY_INIT {0, 0, nullptr}
-template <typename Type, unsigned int StaticSize=8>
-struct hb_vector_t
-{
-  unsigned int len;
-  unsigned int allocated;
-  bool successful;
-  Type *arrayZ;
-  Type static_array[StaticSize];
-
-  void init (void)
-  {
-    len = 0;
-    allocated = ARRAY_LENGTH (static_array);
-    successful = true;
-    arrayZ = static_array;
-  }
-
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len))
-      return Crap (Type);
-    return arrayZ[i];
-  }
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len))
-      return Null(Type);
-    return arrayZ[i];
-  }
-
-  inline Type *push (void)
-  {
-    if (unlikely (!resize (len + 1)))
-      return &Crap(Type);
-    return &arrayZ[len - 1];
-  }
-  inline Type *push (const Type& v)
-  {
-    Type *p = push ();
-    *p = v;
-    return p;
-  }
-
-  /* Allocate for size but don't adjust len. */
-  inline bool alloc (unsigned int size)
-  {
-    if (unlikely (!successful))
-      return false;
-
-    if (likely (size <= allocated))
-      return true;
-
-    /* Reallocate */
-
-    unsigned int new_allocated = allocated;
-    while (size >= new_allocated)
-      new_allocated += (new_allocated >> 1) + 8;
-
-    Type *new_array = nullptr;
-
-    if (arrayZ == static_array)
-    {
-      new_array = (Type *) calloc (new_allocated, sizeof (Type));
-      if (new_array)
-        memcpy (new_array, arrayZ, len * sizeof (Type));
-    }
-    else
-    {
-      bool overflows = (new_allocated < allocated) || _hb_unsigned_int_mul_overflows (new_allocated, sizeof (Type));
-      if (likely (!overflows))
-        new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
-    }
-
-    if (unlikely (!new_array))
-    {
-      successful = false;
-      return false;
-    }
-
-    arrayZ = new_array;
-    allocated = new_allocated;
-
-    return true;
-  }
-
-  inline bool resize (int size_)
-  {
-    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-    if (!alloc (size))
-      return false;
-
-    if (size > len)
-      memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
-
-    len = size;
-    return true;
-  }
-
-  inline void pop (void)
-  {
-    if (!len) return;
-    len--;
-  }
-
-  inline void remove (unsigned int i)
-  {
-     if (unlikely (i >= len))
-       return;
-     memmove (static_cast<void *> (&arrayZ[i]),
-              static_cast<void *> (&arrayZ[i + 1]),
-              (len - i - 1) * sizeof (Type));
-     len--;
-  }
-
-  inline void shrink (int size_)
-  {
-    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-     if (size < len)
-       len = size;
-  }
-
-  template <typename T>
-  inline Type *find (T v) {
-    for (unsigned int i = 0; i < len; i++)
-      if (arrayZ[i] == v)
-        return &arrayZ[i];
-    return nullptr;
-  }
-  template <typename T>
-  inline const Type *find (T v) const {
-    for (unsigned int i = 0; i < len; i++)
-      if (arrayZ[i] == v)
-        return &arrayZ[i];
-    return nullptr;
-  }
-
-  inline void qsort (int (*cmp)(const void*, const void*))
-  {
-    ::qsort (arrayZ, len, sizeof (Type), cmp);
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
-  }
-
-  inline void qsort (unsigned int start, unsigned int end)
-  {
-    ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
-  }
-
-  template <typename T>
-  inline Type *lsearch (const T &x)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      if (0 == this->arrayZ[i].cmp (&x))
-        return &arrayZ[i];
-    return nullptr;
-  }
-
-  template <typename T>
-  inline Type *bsearch (const T &x)
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &arrayZ[i] : nullptr;
-  }
-  template <typename T>
-  inline const Type *bsearch (const T &x) const
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &arrayZ[i] : nullptr;
-  }
-  template <typename T>
-  inline bool bfind (const T &x, unsigned int *i) const
-  {
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = this->arrayZ[mid].cmp (&x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-      {
-        *i = mid;
-        return true;
-      }
-    }
-    if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
-      max++;
-    *i = max;
-    return false;
-  }
-
-  inline void fini (void)
-  {
-    if (arrayZ != static_array)
-      free (arrayZ);
-    arrayZ = nullptr;
-    allocated = len = 0;
-  }
-};
-
-template <typename Type>
-struct hb_auto_t : Type
-{
-  hb_auto_t (void) { Type::init (); }
-  ~hb_auto_t (void) { Type::fini (); }
-  private: /* Hide */
-  void init (void) {}
-  void fini (void) {}
-};
-template <typename Type>
-struct hb_auto_array_t : hb_auto_t <hb_vector_t <Type> > {};
-
-
-#define HB_LOCKABLE_SET_INIT {HB_PREALLOCED_ARRAY_INIT}
-template <typename item_t, typename lock_t>
-struct hb_lockable_set_t
-{
-  hb_vector_t <item_t, 1> items;
-
-  inline void init (void) { items.init (); }
-
-  template <typename T>
-  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      if (replace) {
-        item_t old = *item;
-        *item = v;
-        l.unlock ();
-        old.fini ();
-      }
-      else {
-        item = nullptr;
-        l.unlock ();
-      }
-    } else {
-      item = items.push (v);
-      l.unlock ();
-    }
-    return item;
-  }
-
-  template <typename T>
-  inline void remove (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      item_t old = *item;
-      *item = items[items.len - 1];
-      items.pop ();
-      l.unlock ();
-      old.fini ();
-    } else {
-      l.unlock ();
-    }
-  }
-
-  template <typename T>
-  inline bool find (T v, item_t *i, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item)
-      *i = *item;
-    l.unlock ();
-    return !!item;
-  }
-
-  template <typename T>
-  inline item_t *find_or_insert (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (!item) {
-      item = items.push (v);
-    }
-    l.unlock ();
-    return item;
-  }
-
-  inline void fini (lock_t &l)
-  {
-    if (!items.len) {
-      /* No need for locking. */
-      items.fini ();
-      return;
-    }
-    l.lock ();
-    while (items.len) {
-      item_t old = items[items.len - 1];
-        items.pop ();
-        l.unlock ();
-        old.fini ();
-        l.lock ();
-    }
-    items.fini ();
-    l.unlock ();
-  }
-
-};
-
-
-/* ASCII tag/character handling */
-
-static inline bool ISALPHA (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
-static inline bool ISALNUM (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
-static inline bool ISSPACE (unsigned char c)
-{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
-static inline unsigned char TOUPPER (unsigned char c)
-{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
-static inline unsigned char TOLOWER (unsigned char c)
-{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
-
-
-/* HB_NDEBUG disables some sanity checks that are very safe to disable and
- * should be disabled in production systems.  If NDEBUG is defined, enable
- * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
- * light-weight) to be enabled, then HB_DEBUG can be defined to disable
- * the costlier checks. */
-#ifdef NDEBUG
-#define HB_NDEBUG 1
-#endif
-
-
-/* Misc */
-
-template <typename T> class hb_assert_unsigned_t;
-template <> class hb_assert_unsigned_t<unsigned char> {};
-template <> class hb_assert_unsigned_t<unsigned short> {};
-template <> class hb_assert_unsigned_t<unsigned int> {};
-template <> class hb_assert_unsigned_t<unsigned long> {};
-
-template <typename T> static inline bool
-hb_in_range (T u, T lo, T hi)
-{
-  /* The sizeof() is here to force template instantiation.
-   * I'm sure there are better ways to do this but can't think of
-   * one right now.  Declaring a variable won't work as HB_UNUSED
-   * is unusable on some platforms and unused types are less likely
-   * to generate a warning than unused variables. */
-  static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
-
-  /* The casts below are important as if T is smaller than int,
-   * the subtract results will become a signed int! */
-  return (T)(u - lo) <= (T)(hi - lo);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
-}
-
-
-/* Enable bitwise ops on enums marked as flags_t */
-/* To my surprise, looks like the function resolver is happy to silently cast
- * one enum to another...  So this doesn't provide the type-checking that I
- * originally had in mind... :(.
- *
- * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
- */
-#ifdef _MSC_VER
-# pragma warning(disable:4200)
-# pragma warning(disable:4800)
-#endif
-#define HB_MARK_AS_FLAG_T(T) \
-        extern "C++" { \
-          static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
-          static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
-          static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
-          static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
-          static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
-          static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
-          static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
-        }
-
-
-/* Useful for set-operations on small enums.
- * For example, for testing "x ∈ {x1, x2, x3}" use:
- * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
- */
-#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned int)(x) < 32) + (1U << (unsigned int)(x)))
-#define FLAG_UNSAFE(x) ((unsigned int)(x) < 32 ? (1U << (unsigned int)(x)) : 0)
-#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
-
-
-template <typename T, typename T2> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
-{
-  for (unsigned int i = 1; i < len; i++)
-  {
-    unsigned int j = i;
-    while (j && compar (&array[j - 1], &array[i]) > 0)
-      j--;
-    if (i == j)
-      continue;
-    /* Move item i to occupy place for item j, shift what's in between. */
-    {
-      T t = array[i];
-      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
-      array[j] = t;
-    }
-    if (array2)
-    {
-      T2 t = array2[i];
-      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
-      array2[j] = t;
-    }
-  }
-}
-
-template <typename T> static inline void
-hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
-{
-  hb_stable_sort (array, len, compar, (int *) nullptr);
-}
-
-static inline hb_bool_t
-hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
-{
-  /* Pain because we don't know whether s is nul-terminated. */
-  char buf[64];
-  len = MIN (ARRAY_LENGTH (buf) - 1, len);
-  strncpy (buf, s, len);
-  buf[len] = '\0';
-
-  char *end;
-  errno = 0;
-  unsigned long v = strtoul (buf, &end, base);
-  if (errno) return false;
-  if (*end) return false;
-  *out = v;
-  return true;
-}
-
-
-/* Vectorization */
-
-struct HbOpOr
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
-};
-struct HbOpAnd
-{
-  static const bool passthru_left = false;
-  static const bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
-};
-struct HbOpMinus
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = false;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
-};
-struct HbOpXor
-{
-  static const bool passthru_left = true;
-  static const bool passthru_right = true;
-  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
-};
-
-
-/* Compiler-assisted vectorization. */
-
-/* The `vector_size' attribute was introduced in gcc 3.1. */
-#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
-#define HB_VECTOR_SIZE 128
-#elif !defined(HB_VECTOR_SIZE)
-#define HB_VECTOR_SIZE 0
-#endif
-
-/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */
-template <typename elt_t, unsigned int byte_size>
-struct hb_vector_size_t
-{
-  elt_t& operator [] (unsigned int i) { return u.v[i]; }
-  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
-
-  template <class Op>
-  inline hb_vector_size_t process (const hb_vector_size_t &o) const
-  {
-    hb_vector_size_t r;
-#if HB_VECTOR_SIZE
-    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-        Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
-    else
-#endif
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-        Op::process (r.u.v[i], u.v[i], o.u.v[i]);
-    return r;
-  }
-  inline hb_vector_size_t operator | (const hb_vector_size_t &o) const
-  { return process<HbOpOr> (o); }
-  inline hb_vector_size_t operator & (const hb_vector_size_t &o) const
-  { return process<HbOpAnd> (o); }
-  inline hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
-  { return process<HbOpXor> (o); }
-  inline hb_vector_size_t operator ~ () const
-  {
-    hb_vector_size_t r;
-#if HB_VECTOR_SIZE && 0
-    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-        r.u.vec[i] = ~u.vec[i];
-    else
-#endif
-    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-      r.u.v[i] = ~u.v[i];
-    return r;
-  }
-
-  private:
-  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
-  union {
-    elt_t v[byte_size / sizeof (elt_t)];
-#if HB_VECTOR_SIZE
-    typedef unsigned long vec_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
-    vec_t vec[byte_size / sizeof (vec_t)];
-#endif
-  } u;
-};
-
-
-/* Global runtime options. */
-
-struct hb_options_t
-{
-  unsigned int initialized : 1;
-  unsigned int uniscribe_bug_compatible : 1;
-};
-
-union hb_options_union_t {
-  unsigned int i;
-  hb_options_t opts;
-};
-static_assert ((sizeof (int) == sizeof (hb_options_union_t)), "");
-
-HB_INTERNAL void
-_hb_options_init (void);
-
-extern HB_INTERNAL hb_options_union_t _hb_options;
-
-static inline hb_options_t
-hb_options (void)
-{
-  if (unlikely (!_hb_options.i))
-    _hb_options_init ();
-
-  return _hb_options.opts;
-}
-
-/* Size signifying variable-sized array */
-#define VAR 1
-
-
-/* String type. */
-
-struct hb_bytes_t
-{
-  inline hb_bytes_t (void) : bytes (nullptr), len (0) {}
-  inline hb_bytes_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
-
-  inline int cmp (const hb_bytes_t &a) const
-  {
-    if (len != a.len)
-      return (int) a.len - (int) len;
-
-    return memcmp (a.bytes, bytes, len);
-  }
-  static inline int cmp (const void *pa, const void *pb)
-  {
-    hb_bytes_t *a = (hb_bytes_t *) pa;
-    hb_bytes_t *b = (hb_bytes_t *) pb;
-    return b->cmp (*a);
-  }
-
-  const char *bytes;
-  unsigned int len;
-};
-
-
-/* fallback for round() */
-#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
-static inline double
-_hb_round (double x)
-{
-  if (x >= 0)
-    return floor (x + 0.5);
-  else
-    return ceil (x - 0.5);
-}
-#define round(x) _hb_round(x)
-#endif
-
-
-#endif /* HB_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-digest-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SET_DIGEST_PRIVATE_HH
-#define HB_SET_DIGEST_PRIVATE_HH
-
-#include "hb-private.hh"
-
-/*
- * The set digests here implement various "filters" that support
- * "approximate member query".  Conceptually these are like Bloom
- * Filter and Quotient Filter, however, much smaller, faster, and
- * designed to fit the requirements of our uses for glyph coverage
- * queries.
- *
- * Our filters are highly accurate if the lookup covers fairly local
- * set of glyphs, but fully flooded and ineffective if coverage is
- * all over the place.
- *
- * The frozen-set can be used instead of a digest, to trade more
- * memory for 100% accuracy, but in practice, that doesn't look like
- * an attractive trade-off.
- */
-
-template <typename mask_t, unsigned int shift>
-struct hb_set_digest_lowest_bits_t
-{
-  ASSERT_POD ();
-
-  static const unsigned int mask_bytes = sizeof (mask_t);
-  static const unsigned int mask_bits = sizeof (mask_t) * 8;
-  static const unsigned int num_bits = 0
-                                     + (mask_bytes >= 1 ? 3 : 0)
-                                     + (mask_bytes >= 2 ? 1 : 0)
-                                     + (mask_bytes >= 4 ? 1 : 0)
-                                     + (mask_bytes >= 8 ? 1 : 0)
-                                     + (mask_bytes >= 16? 1 : 0)
-                                     + 0;
-
-  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
-  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
-
-  inline void init (void) {
-    mask = 0;
-  }
-
-  inline void add (hb_codepoint_t g) {
-    mask |= mask_for (g);
-  }
-
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) {
-    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
-      mask = (mask_t) -1;
-    else {
-      mask_t ma = mask_for (a);
-      mask_t mb = mask_for (b);
-      mask |= mb + (mb - ma) - (mb < ma);
-    }
-    return true;
-  }
-
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    for (unsigned int i = 0; i < count; i++)
-    {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
-    }
-  }
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    for (unsigned int i = 0; i < count; i++)
-    {
-      add (*array);
-      array = (const T *) (stride + (const char *) array);
-    }
-    return true;
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return !!(mask & mask_for (g));
-  }
-
-  private:
-
-  static inline mask_t mask_for (hb_codepoint_t g) {
-    return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1));
-  }
-  mask_t mask;
-};
-
-template <typename head_t, typename tail_t>
-struct hb_set_digest_combiner_t
-{
-  ASSERT_POD ();
-
-  inline void init (void) {
-    head.init ();
-    tail.init ();
-  }
-
-  inline void add (hb_codepoint_t g) {
-    head.add (g);
-    tail.add (g);
-  }
-
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b) {
-    head.add_range (a, b);
-    tail.add_range (a, b);
-    return true;
-  }
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    head.add_array (array, count, stride);
-    tail.add_array (array, count, stride);
-  }
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    head.add_sorted_array (array, count, stride);
-    tail.add_sorted_array (array, count, stride);
-    return true;
-  }
-
-  inline bool may_have (hb_codepoint_t g) const {
-    return head.may_have (g) && tail.may_have (g);
-  }
-
-  private:
-  head_t head;
-  tail_t tail;
-};
-
-
-/*
- * hb_set_digest_t
- *
- * This is a combination of digests that performs "best".
- * There is not much science to this: it's a result of intuition
- * and testing.
- */
-typedef hb_set_digest_combiner_t
-<
-  hb_set_digest_lowest_bits_t<unsigned long, 4>,
-  hb_set_digest_combiner_t
-  <
-    hb_set_digest_lowest_bits_t<unsigned long, 0>,
-    hb_set_digest_lowest_bits_t<unsigned long, 9>
-  >
-> hb_set_digest_t;
-
-
-#endif /* HB_SET_DIGEST_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-digest.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SET_DIGEST_HH
+#define HB_SET_DIGEST_HH
+
+#include "hb.hh"
+
+/*
+ * The set digests here implement various "filters" that support
+ * "approximate member query".  Conceptually these are like Bloom
+ * Filter and Quotient Filter, however, much smaller, faster, and
+ * designed to fit the requirements of our uses for glyph coverage
+ * queries.
+ *
+ * Our filters are highly accurate if the lookup covers fairly local
+ * set of glyphs, but fully flooded and ineffective if coverage is
+ * all over the place.
+ *
+ * The frozen-set can be used instead of a digest, to trade more
+ * memory for 100% accuracy, but in practice, that doesn't look like
+ * an attractive trade-off.
+ */
+
+template <typename mask_t, unsigned int shift>
+struct hb_set_digest_lowest_bits_t
+{
+  static constexpr unsigned mask_bytes = sizeof (mask_t);
+  static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
+  static constexpr unsigned num_bits = 0
+                                     + (mask_bytes >= 1 ? 3 : 0)
+                                     + (mask_bytes >= 2 ? 1 : 0)
+                                     + (mask_bytes >= 4 ? 1 : 0)
+                                     + (mask_bytes >= 8 ? 1 : 0)
+                                     + (mask_bytes >= 16? 1 : 0)
+                                     + 0;
+
+  static_assert ((shift < sizeof (hb_codepoint_t) * 8), "");
+  static_assert ((shift + num_bits <= sizeof (hb_codepoint_t) * 8), "");
+
+  void init () { mask = 0; }
+
+  void add (hb_codepoint_t g) { mask |= mask_for (g); }
+
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    if ((b >> shift) - (a >> shift) >= mask_bits - 1)
+      mask = (mask_t) -1;
+    else {
+      mask_t ma = mask_for (a);
+      mask_t mb = mask_for (b);
+      mask |= mb + (mb - ma) - (mb < ma);
+    }
+    return true;
+  }
+
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      add (*array);
+      array = (const T *) (stride + (const char *) array);
+    }
+  }
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    for (unsigned int i = 0; i < count; i++)
+    {
+      add (*array);
+      array = (const T *) (stride + (const char *) array);
+    }
+    return true;
+  }
+
+  bool may_have (hb_codepoint_t g) const
+  { return !!(mask & mask_for (g)); }
+
+  private:
+
+  static mask_t mask_for (hb_codepoint_t g)
+  { return ((mask_t) 1) << ((g >> shift) & (mask_bits - 1)); }
+  mask_t mask;
+};
+
+template <typename head_t, typename tail_t>
+struct hb_set_digest_combiner_t
+{
+  void init ()
+  {
+    head.init ();
+    tail.init ();
+  }
+
+  void add (hb_codepoint_t g)
+  {
+    head.add (g);
+    tail.add (g);
+  }
+
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    head.add_range (a, b);
+    tail.add_range (a, b);
+    return true;
+  }
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    head.add_array (array, count, stride);
+    tail.add_array (array, count, stride);
+  }
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    head.add_sorted_array (array, count, stride);
+    tail.add_sorted_array (array, count, stride);
+    return true;
+  }
+
+  bool may_have (hb_codepoint_t g) const
+  {
+    return head.may_have (g) && tail.may_have (g);
+  }
+
+  private:
+  head_t head;
+  tail_t tail;
+};
+
+
+/*
+ * hb_set_digest_t
+ *
+ * This is a combination of digests that performs "best".
+ * There is not much science to this: it's a result of intuition
+ * and testing.
+ */
+typedef hb_set_digest_combiner_t
+<
+  hb_set_digest_lowest_bits_t<unsigned long, 4>,
+  hb_set_digest_combiner_t
+  <
+    hb_set_digest_lowest_bits_t<unsigned long, 0>,
+    hb_set_digest_lowest_bits_t<unsigned long, 9>
+  >
+> hb_set_digest_t;
+
+
+#endif /* HB_SET_DIGEST_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,700 +0,0 @@
-/*
- * Copyright © 2012,2017  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SET_PRIVATE_HH
-#define HB_SET_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-/*
- * hb_set_t
- */
-
-/* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
- * point maybe also use a sentinel value for "all-1" pages? */
-
-struct hb_set_t
-{
-  struct page_map_t
-  {
-    inline int cmp (const page_map_t *o) const { return (int) o->major - (int) major; }
-
-    uint32_t major;
-    uint32_t index;
-  };
-
-  struct page_t
-  {
-    inline void init0 (void) { memset (&v, 0, sizeof (v)); }
-    inline void init1 (void) { memset (&v, 0xff, sizeof (v)); }
-
-    inline unsigned int len (void) const
-    { return ARRAY_LENGTH_CONST (v); }
-
-    inline bool is_empty (void) const
-    {
-      for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
-          return false;
-      return true;
-    }
-
-    inline void add (hb_codepoint_t g) { elt (g) |= mask (g); }
-    inline void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
-    inline bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
-
-    inline void add_range (hb_codepoint_t a, hb_codepoint_t b)
-    {
-      elt_t *la = &elt (a);
-      elt_t *lb = &elt (b);
-      if (la == lb)
-        *la |= (mask (b) << 1) - mask(a);
-      else
-      {
-        *la |= ~(mask (a) - 1);
-        la++;
-
-        memset (la, 0xff, (char *) lb - (char *) la);
-
-        *lb |= ((mask (b) << 1) - 1);
-      }
-    }
-
-    inline bool is_equal (const page_t *other) const
-    {
-      return 0 == memcmp (&v, &other->v, sizeof (v));
-    }
-
-    inline unsigned int get_population (void) const
-    {
-      unsigned int pop = 0;
-      for (unsigned int i = 0; i < len (); i++)
-        pop += _hb_popcount (v[i]);
-      return pop;
-    }
-
-    inline bool next (hb_codepoint_t *codepoint) const
-    {
-      unsigned int m = (*codepoint + 1) & MASK;
-      if (!m)
-      {
-        *codepoint = INVALID;
-        return false;
-      }
-      unsigned int i = m / ELT_BITS;
-      unsigned int j = m & ELT_MASK;
-
-      const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
-      for (const elt_t *p = &vv; i < len (); p = &v[++i])
-        if (*p)
-        {
-          *codepoint = i * ELT_BITS + elt_get_min (*p);
-          return true;
-        }
-
-      *codepoint = INVALID;
-      return false;
-    }
-    inline bool previous (hb_codepoint_t *codepoint) const
-    {
-      unsigned int m = (*codepoint - 1) & MASK;
-      if (m == MASK)
-      {
-        *codepoint = INVALID;
-        return false;
-      }
-      unsigned int i = m / ELT_BITS;
-      unsigned int j = m & ELT_MASK;
-
-      const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
-      for (const elt_t *p = &vv; (int) i >= 0; p = &v[--i])
-        if (*p)
-        {
-          *codepoint = i * ELT_BITS + elt_get_max (*p);
-          return true;
-        }
-
-      *codepoint = INVALID;
-      return false;
-    }
-    inline hb_codepoint_t get_min (void) const
-    {
-      for (unsigned int i = 0; i < len (); i++)
-        if (v[i])
-          return i * ELT_BITS + elt_get_min (v[i]);
-      return INVALID;
-    }
-    inline hb_codepoint_t get_max (void) const
-    {
-      for (int i = len () - 1; i >= 0; i--)
-        if (v[i])
-          return i * ELT_BITS + elt_get_max (v[i]);
-      return 0;
-    }
-
-    typedef unsigned long long elt_t;
-    static const unsigned int PAGE_BITS = 512;
-    static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
-
-    static inline unsigned int elt_get_min (const elt_t &elt) { return _hb_ctz (elt); }
-    static inline unsigned int elt_get_max (const elt_t &elt) { return _hb_bit_storage (elt) - 1; }
-
-    typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
-
-    static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
-    static const unsigned int ELT_MASK = ELT_BITS - 1;
-    static const unsigned int BITS = sizeof (vector_t) * 8;
-    static const unsigned int MASK = BITS - 1;
-    static_assert (PAGE_BITS == BITS, "");
-
-    elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
-    elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
-    elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
-
-    vector_t v;
-  };
-  static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
-
-  hb_object_header_t header;
-  bool successful; /* Allocations successful */
-  mutable unsigned int population;
-  hb_vector_t<page_map_t, 1> page_map;
-  hb_vector_t<page_t, 1> pages;
-
-  inline void init_shallow (void)
-  {
-    successful = true;
-    population = 0;
-    page_map.init ();
-    pages.init ();
-  }
-  inline void init (void)
-  {
-    hb_object_init (this);
-    init_shallow ();
-  }
-  inline void fini_shallow (void)
-  {
-    page_map.fini ();
-    pages.fini ();
-  }
-  inline void fini (void)
-  {
-    hb_object_fini (this);
-    fini_shallow ();
-  }
-
-  inline bool resize (unsigned int count)
-  {
-    if (unlikely (!successful)) return false;
-    if (!pages.resize (count) || !page_map.resize (count))
-    {
-      pages.resize (page_map.len);
-      successful = false;
-      return false;
-    }
-    return true;
-  }
-
-  inline void clear (void) {
-    if (unlikely (hb_object_is_inert (this)))
-      return;
-    successful = true;
-    population = 0;
-    page_map.resize (0);
-    pages.resize (0);
-  }
-  inline bool is_empty (void) const {
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!pages[i].is_empty ())
-        return false;
-    return true;
-  }
-
-  inline void dirty (void) { population = (unsigned int) -1; }
-
-  inline void add (hb_codepoint_t g)
-  {
-    if (unlikely (!successful)) return;
-    if (unlikely (g == INVALID)) return;
-    dirty ();
-    page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-    page->add (g);
-  }
-  inline bool add_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
-    if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
-    dirty ();
-    unsigned int ma = get_major (a);
-    unsigned int mb = get_major (b);
-    if (ma == mb)
-    {
-      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
-      page->add_range (a, b);
-    }
-    else
-    {
-      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
-      page->add_range (a, major_start (ma + 1) - 1);
-
-      for (unsigned int m = ma + 1; m < mb; m++)
-      {
-        page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
-        page->init1 ();
-      }
-
-      page = page_for_insert (b); if (unlikely (!page)) return false;
-      page->add_range (major_start (mb), b);
-    }
-    return true;
-  }
-
-  template <typename T>
-  inline void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    if (unlikely (!successful)) return;
-    if (!count) return;
-    dirty ();
-    hb_codepoint_t g = *array;
-    while (count)
-    {
-      unsigned int m = get_major (g);
-      page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-      unsigned int start = major_start (m);
-      unsigned int end = major_start (m + 1);
-      do
-      {
-        page->add (g);
-
-        array = (const T *) ((const char *) array + stride);
-        count--;
-      }
-      while (count && (g = *array, start <= g && g < end));
-    }
-  }
-
-  /* Might return false if array looks unsorted.
-   * Used for faster rejection of corrupt data. */
-  template <typename T>
-  inline bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
-  {
-    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
-    if (!count) return true;
-    dirty ();
-    hb_codepoint_t g = *array;
-    hb_codepoint_t last_g = g;
-    while (count)
-    {
-      unsigned int m = get_major (g);
-      page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
-      unsigned int end = major_start (m + 1);
-      do
-      {
-        /* If we try harder we can change the following comparison to <=;
-         * Not sure if it's worth it. */
-        if (g < last_g) return false;
-        last_g = g;
-        page->add (g);
-
-        array = (const T *) ((const char *) array + stride);
-        count--;
-      }
-      while (count && (g = *array, g < end));
-    }
-    return true;
-  }
-
-  inline void del (hb_codepoint_t g)
-  {
-    /* TODO perform op even if !successful. */
-    if (unlikely (!successful)) return;
-    page_t *p = page_for (g);
-    if (!p)
-      return;
-    dirty ();
-    p->del (g);
-  }
-  inline void del_range (hb_codepoint_t a, hb_codepoint_t b)
-  {
-    /* TODO perform op even if !successful. */
-    /* TODO Optimize, like add_range(). */
-    if (unlikely (!successful)) return;
-    for (unsigned int i = a; i < b + 1; i++)
-      del (i);
-  }
-  inline bool has (hb_codepoint_t g) const
-  {
-    const page_t *p = page_for (g);
-    if (!p)
-      return false;
-    return p->has (g);
-  }
-  inline bool intersects (hb_codepoint_t first,
-                          hb_codepoint_t last) const
-  {
-    hb_codepoint_t c = first - 1;
-    return next (&c) && c <= last;
-  }
-  inline void set (const hb_set_t *other)
-  {
-    if (unlikely (!successful)) return;
-    unsigned int count = other->pages.len;
-    if (!resize (count))
-      return;
-    population = other->population;
-    memcpy (pages.arrayZ, other->pages.arrayZ, count * sizeof (pages.arrayZ[0]));
-    memcpy (page_map.arrayZ, other->page_map.arrayZ, count * sizeof (page_map.arrayZ[0]));
-  }
-
-  inline bool is_equal (const hb_set_t *other) const
-  {
-    if (get_population () != other->get_population ())
-      return false;
-
-    unsigned int na = pages.len;
-    unsigned int nb = other->pages.len;
-
-    unsigned int a = 0, b = 0;
-    for (; a < na && b < nb; )
-    {
-      if (page_at (a).is_empty ()) { a++; continue; }
-      if (other->page_at (b).is_empty ()) { b++; continue; }
-      if (page_map[a].major != other->page_map[b].major ||
-          !page_at (a).is_equal (&other->page_at (b)))
-        return false;
-      a++;
-      b++;
-    }
-    for (; a < na; a++)
-      if (!page_at (a).is_empty ()) { return false; }
-    for (; b < nb; b++)
-      if (!other->page_at (b).is_empty ()) { return false; }
-
-    return true;
-  }
-
-  inline bool is_subset (const hb_set_t *larger_set) const
-  {
-    if (get_population () > larger_set->get_population ())
-      return false;
-
-    hb_codepoint_t c = INVALID;
-    while (next (&c))
-      if (!larger_set->has (c))
-        return false;
-
-    return true;
-  }
-
-  template <class Op>
-  inline void process (const hb_set_t *other)
-  {
-    if (unlikely (!successful)) return;
-
-    dirty ();
-
-    unsigned int na = pages.len;
-    unsigned int nb = other->pages.len;
-    unsigned int next_page = na;
-
-    unsigned int count = 0, newCount = 0;
-    unsigned int a = 0, b = 0;
-    for (; a < na && b < nb; )
-    {
-      if (page_map[a].major == other->page_map[b].major)
-      {
-        count++;
-        a++;
-        b++;
-      }
-      else if (page_map[a].major < other->page_map[b].major)
-      {
-        if (Op::passthru_left)
-          count++;
-        a++;
-      }
-      else
-      {
-        if (Op::passthru_right)
-          count++;
-        b++;
-      }
-    }
-    if (Op::passthru_left)
-      count += na - a;
-    if (Op::passthru_right)
-      count += nb - b;
-
-    if (count > pages.len)
-      if (!resize (count))
-        return;
-    newCount = count;
-
-    /* Process in-place backward. */
-    a = na;
-    b = nb;
-    for (; a && b; )
-    {
-      if (page_map[a - 1].major == other->page_map[b - 1].major)
-      {
-        a--;
-        b--;
-        count--;
-        page_map[count] = page_map[a];
-        Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
-      }
-      else if (page_map[a - 1].major > other->page_map[b - 1].major)
-      {
-        a--;
-        if (Op::passthru_left)
-        {
-          count--;
-          page_map[count] = page_map[a];
-        }
-      }
-      else
-      {
-        b--;
-        if (Op::passthru_right)
-        {
-          count--;
-          page_map[count].major = other->page_map[b].major;
-          page_map[count].index = next_page++;
-          page_at (count).v = other->page_at (b).v;
-        }
-      }
-    }
-    if (Op::passthru_left)
-      while (a)
-      {
-        a--;
-        count--;
-        page_map[count] = page_map [a];
-      }
-    if (Op::passthru_right)
-      while (b)
-      {
-        b--;
-        count--;
-        page_map[count].major = other->page_map[b].major;
-        page_map[count].index = next_page++;
-        page_at (count).v = other->page_at (b).v;
-      }
-    assert (!count);
-    if (pages.len > newCount)
-      resize (newCount);
-  }
-
-  inline void union_ (const hb_set_t *other)
-  {
-    process<HbOpOr> (other);
-  }
-  inline void intersect (const hb_set_t *other)
-  {
-    process<HbOpAnd> (other);
-  }
-  inline void subtract (const hb_set_t *other)
-  {
-    process<HbOpMinus> (other);
-  }
-  inline void symmetric_difference (const hb_set_t *other)
-  {
-    process<HbOpXor> (other);
-  }
-  inline bool next (hb_codepoint_t *codepoint) const
-  {
-    if (unlikely (*codepoint == INVALID)) {
-      *codepoint = get_min ();
-      return *codepoint != INVALID;
-    }
-
-    page_map_t map = {get_major (*codepoint), 0};
-    unsigned int i;
-    page_map.bfind (map, &i);
-    if (i < page_map.len && page_map[i].major == map.major)
-    {
-      if (pages[page_map[i].index].next (codepoint))
-      {
-        *codepoint += page_map[i].major * page_t::PAGE_BITS;
-        return true;
-      }
-      i++;
-    }
-    for (; i < page_map.len; i++)
-    {
-      hb_codepoint_t m = pages[page_map[i].index].get_min ();
-      if (m != INVALID)
-      {
-        *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
-        return true;
-      }
-    }
-    *codepoint = INVALID;
-    return false;
-  }
-  inline bool previous (hb_codepoint_t *codepoint) const
-  {
-    if (unlikely (*codepoint == INVALID)) {
-      *codepoint = get_max ();
-      return *codepoint != INVALID;
-    }
-
-    page_map_t map = {get_major (*codepoint), 0};
-    unsigned int i;
-    page_map.bfind (map, &i);
-    if (i < page_map.len && page_map[i].major == map.major)
-    {
-      if (pages[page_map[i].index].previous (codepoint))
-      {
-        *codepoint += page_map[i].major * page_t::PAGE_BITS;
-        return true;
-      }
-    }
-    i--;
-    for (; (int) i >= 0; i--)
-    {
-      hb_codepoint_t m = pages[page_map[i].index].get_max ();
-      if (m != INVALID)
-      {
-        *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
-        return true;
-      }
-    }
-    *codepoint = INVALID;
-    return false;
-  }
-  inline bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
-  {
-    hb_codepoint_t i;
-
-    i = *last;
-    if (!next (&i))
-    {
-      *last = *first = INVALID;
-      return false;
-    }
-
-    /* TODO Speed up. */
-    *last = *first = i;
-    while (next (&i) && i == *last + 1)
-      (*last)++;
-
-    return true;
-  }
-  inline bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
-  {
-    hb_codepoint_t i;
-
-    i = *first;
-    if (!previous (&i))
-    {
-      *last = *first = INVALID;
-      return false;
-    }
-
-    /* TODO Speed up. */
-    *last = *first = i;
-    while (previous (&i) && i == *first - 1)
-      (*first)--;
-
-    return true;
-  }
-
-  inline unsigned int get_population (void) const
-  {
-    if (population != (unsigned int) -1)
-      return population;
-
-    unsigned int pop = 0;
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      pop += pages[i].get_population ();
-
-    population = pop;
-    return pop;
-  }
-  inline hb_codepoint_t get_min (void) const
-  {
-    unsigned int count = pages.len;
-    for (unsigned int i = 0; i < count; i++)
-      if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
-    return INVALID;
-  }
-  inline hb_codepoint_t get_max (void) const
-  {
-    unsigned int count = pages.len;
-    for (int i = count - 1; i >= 0; i++)
-      if (!page_at (i).is_empty ())
-        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_max ();
-    return INVALID;
-  }
-
-  static  const hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
-
-  inline page_t *page_for_insert (hb_codepoint_t g)
-  {
-    page_map_t map = {get_major (g), pages.len};
-    unsigned int i;
-    if (!page_map.bfind (map, &i))
-    {
-      if (!resize (pages.len + 1))
-        return nullptr;
-
-      pages[map.index].init0 ();
-      memmove (&page_map[i + 1], &page_map[i], (page_map.len - 1 - i) * sizeof (page_map[0]));
-      page_map[i] = map;
-    }
-    return &pages[page_map[i].index];
-  }
-  inline page_t *page_for (hb_codepoint_t g)
-  {
-    page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (key);
-    if (found)
-      return &pages[found->index];
-    return nullptr;
-  }
-  inline const page_t *page_for (hb_codepoint_t g) const
-  {
-    page_map_t key = {get_major (g)};
-    const page_map_t *found = page_map.bsearch (key);
-    if (found)
-      return &pages[found->index];
-    return nullptr;
-  }
-  inline page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
-  inline const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
-  inline unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
-  inline hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
-};
-
-
-#endif /* HB_SET_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,10 +24,19 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-set-private.hh"
+#include "hb-set.hh"
 
 
-/* Public API */
+/**
+ * SECTION:hb-set
+ * @title: hb-set
+ * @short_description: Object representing a set of integers
+ * @include: hb.h
+ *
+ * Set objects represent a mathematical set of integer values.  They are
+ * used in non-shaping API to query certain set of characters or glyphs,
+ * or other integer values.
+ **/
 
 
 /**
@@ -38,7 +47,7 @@
  * Since: 0.9.2
  **/
 hb_set_t *
-hb_set_create (void)
+hb_set_create ()
 {
   hb_set_t *set;
 
@@ -58,7 +67,7 @@
  * Since: 0.9.2
  **/
 hb_set_t *
-hb_set_get_empty (void)
+hb_set_get_empty ()
 {
   return const_cast<hb_set_t *> (&Null(hb_set_t));
 }
@@ -391,7 +400,7 @@
  * Deprecated: 1.6.1
  **/
 void
-hb_set_invert (hb_set_t *set)
+hb_set_invert (hb_set_t *set HB_UNUSED)
 {
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-set.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,738 @@
+/*
+ * Copyright © 2012,2017  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SET_HH
+#define HB_SET_HH
+
+#include "hb.hh"
+
+
+/*
+ * hb_set_t
+ */
+
+/* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
+ * point maybe also use a sentinel value for "all-1" pages? */
+
+struct hb_set_t
+{
+  HB_NO_COPY_ASSIGN (hb_set_t);
+  hb_set_t ()  { init (); }
+  ~hb_set_t () { fini (); }
+
+  struct page_map_t
+  {
+    int cmp (const page_map_t &o) const { return (int) o.major - (int) major; }
+
+    uint32_t major;
+    uint32_t index;
+  };
+
+  struct page_t
+  {
+    void init0 () { v.clear (); }
+    void init1 () { v.clear (0xFF); }
+
+    unsigned int len () const
+    { return ARRAY_LENGTH_CONST (v); }
+
+    bool is_empty () const
+    {
+      for (unsigned int i = 0; i < len (); i++)
+        if (v[i])
+          return false;
+      return true;
+    }
+
+    void add (hb_codepoint_t g) { elt (g) |= mask (g); }
+    void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
+    bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
+
+    void add_range (hb_codepoint_t a, hb_codepoint_t b)
+    {
+      elt_t *la = &elt (a);
+      elt_t *lb = &elt (b);
+      if (la == lb)
+        *la |= (mask (b) << 1) - mask(a);
+      else
+      {
+        *la |= ~(mask (a) - 1);
+        la++;
+
+        memset (la, 0xff, (char *) lb - (char *) la);
+
+        *lb |= ((mask (b) << 1) - 1);
+      }
+    }
+
+    bool is_equal (const page_t *other) const
+    {
+      return 0 == hb_memcmp (&v, &other->v, sizeof (v));
+    }
+
+    unsigned int get_population () const
+    {
+      unsigned int pop = 0;
+      for (unsigned int i = 0; i < len (); i++)
+        pop += hb_popcount (v[i]);
+      return pop;
+    }
+
+    bool next (hb_codepoint_t *codepoint) const
+    {
+      unsigned int m = (*codepoint + 1) & MASK;
+      if (!m)
+      {
+        *codepoint = INVALID;
+        return false;
+      }
+      unsigned int i = m / ELT_BITS;
+      unsigned int j = m & ELT_MASK;
+
+      const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
+      for (const elt_t *p = &vv; i < len (); p = &v[++i])
+        if (*p)
+        {
+          *codepoint = i * ELT_BITS + elt_get_min (*p);
+          return true;
+        }
+
+      *codepoint = INVALID;
+      return false;
+    }
+    bool previous (hb_codepoint_t *codepoint) const
+    {
+      unsigned int m = (*codepoint - 1) & MASK;
+      if (m == MASK)
+      {
+        *codepoint = INVALID;
+        return false;
+      }
+      unsigned int i = m / ELT_BITS;
+      unsigned int j = m & ELT_MASK;
+
+      const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
+      for (const elt_t *p = &vv; (int) i >= 0; p = &v[--i])
+        if (*p)
+        {
+          *codepoint = i * ELT_BITS + elt_get_max (*p);
+          return true;
+        }
+
+      *codepoint = INVALID;
+      return false;
+    }
+    hb_codepoint_t get_min () const
+    {
+      for (unsigned int i = 0; i < len (); i++)
+        if (v[i])
+          return i * ELT_BITS + elt_get_min (v[i]);
+      return INVALID;
+    }
+    hb_codepoint_t get_max () const
+    {
+      for (int i = len () - 1; i >= 0; i--)
+        if (v[i])
+          return i * ELT_BITS + elt_get_max (v[i]);
+      return 0;
+    }
+
+    typedef unsigned long long elt_t;
+    static constexpr unsigned PAGE_BITS = 512;
+    static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
+
+    static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
+    static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
+
+    typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
+
+    static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
+    static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+    static constexpr unsigned BITS = sizeof (vector_t) * 8;
+    static constexpr unsigned MASK = BITS - 1;
+    static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
+
+    elt_t &elt (hb_codepoint_t g) { return v[(g & MASK) / ELT_BITS]; }
+    elt_t const &elt (hb_codepoint_t g) const { return v[(g & MASK) / ELT_BITS]; }
+    elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & ELT_MASK); }
+
+    vector_t v;
+  };
+  static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
+
+  hb_object_header_t header;
+  bool successful; /* Allocations successful */
+  mutable unsigned int population;
+  hb_vector_t<page_map_t> page_map;
+  hb_vector_t<page_t> pages;
+
+  void init_shallow ()
+  {
+    successful = true;
+    population = 0;
+    page_map.init ();
+    pages.init ();
+  }
+  void init ()
+  {
+    hb_object_init (this);
+    init_shallow ();
+  }
+  void fini_shallow ()
+  {
+    population = 0;
+    page_map.fini ();
+    pages.fini ();
+  }
+  void fini ()
+  {
+    hb_object_fini (this);
+    fini_shallow ();
+  }
+
+  bool in_error () const { return !successful; }
+
+  bool resize (unsigned int count)
+  {
+    if (unlikely (!successful)) return false;
+    if (!pages.resize (count) || !page_map.resize (count))
+    {
+      pages.resize (page_map.length);
+      successful = false;
+      return false;
+    }
+    return true;
+  }
+
+  void clear ()
+  {
+    if (unlikely (hb_object_is_immutable (this)))
+      return;
+    successful = true;
+    population = 0;
+    page_map.resize (0);
+    pages.resize (0);
+  }
+  bool is_empty () const
+  {
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!pages[i].is_empty ())
+        return false;
+    return true;
+  }
+
+  void dirty () { population = (unsigned int) -1; }
+
+  void add (hb_codepoint_t g)
+  {
+    if (unlikely (!successful)) return;
+    if (unlikely (g == INVALID)) return;
+    dirty ();
+    page_t *page = page_for_insert (g); if (unlikely (!page)) return;
+    page->add (g);
+  }
+  bool add_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+    if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
+    dirty ();
+    unsigned int ma = get_major (a);
+    unsigned int mb = get_major (b);
+    if (ma == mb)
+    {
+      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
+      page->add_range (a, b);
+    }
+    else
+    {
+      page_t *page = page_for_insert (a); if (unlikely (!page)) return false;
+      page->add_range (a, major_start (ma + 1) - 1);
+
+      for (unsigned int m = ma + 1; m < mb; m++)
+      {
+        page = page_for_insert (major_start (m)); if (unlikely (!page)) return false;
+        page->init1 ();
+      }
+
+      page = page_for_insert (b); if (unlikely (!page)) return false;
+      page->add_range (major_start (mb), b);
+    }
+    return true;
+  }
+
+  template <typename T>
+  void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    if (unlikely (!successful)) return;
+    if (!count) return;
+    dirty ();
+    hb_codepoint_t g = *array;
+    while (count)
+    {
+      unsigned int m = get_major (g);
+      page_t *page = page_for_insert (g); if (unlikely (!page)) return;
+      unsigned int start = major_start (m);
+      unsigned int end = major_start (m + 1);
+      do
+      {
+        page->add (g);
+
+        array = (const T *) ((const char *) array + stride);
+        count--;
+      }
+      while (count && (g = *array, start <= g && g < end));
+    }
+  }
+
+  /* Might return false if array looks unsorted.
+   * Used for faster rejection of corrupt data. */
+  template <typename T>
+  bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
+  {
+    if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
+    if (!count) return true;
+    dirty ();
+    hb_codepoint_t g = *array;
+    hb_codepoint_t last_g = g;
+    while (count)
+    {
+      unsigned int m = get_major (g);
+      page_t *page = page_for_insert (g); if (unlikely (!page)) return false;
+      unsigned int end = major_start (m + 1);
+      do
+      {
+        /* If we try harder we can change the following comparison to <=;
+         * Not sure if it's worth it. */
+        if (g < last_g) return false;
+        last_g = g;
+        page->add (g);
+
+        array = (const T *) ((const char *) array + stride);
+        count--;
+      }
+      while (count && (g = *array, g < end));
+    }
+    return true;
+  }
+
+  void del (hb_codepoint_t g)
+  {
+    /* TODO perform op even if !successful. */
+    if (unlikely (!successful)) return;
+    page_t *page = page_for (g);
+    if (!page)
+      return;
+    dirty ();
+    page->del (g);
+  }
+  void del_range (hb_codepoint_t a, hb_codepoint_t b)
+  {
+    /* TODO perform op even if !successful. */
+    /* TODO Optimize, like add_range(). */
+    if (unlikely (!successful)) return;
+    for (unsigned int i = a; i < b + 1; i++)
+      del (i);
+  }
+  bool has (hb_codepoint_t g) const
+  {
+    const page_t *page = page_for (g);
+    if (!page)
+      return false;
+    return page->has (g);
+  }
+  bool intersects (hb_codepoint_t first,
+                          hb_codepoint_t last) const
+  {
+    hb_codepoint_t c = first - 1;
+    return next (&c) && c <= last;
+  }
+  void set (const hb_set_t *other)
+  {
+    if (unlikely (!successful)) return;
+    unsigned int count = other->pages.length;
+    if (!resize (count))
+      return;
+    population = other->population;
+    memcpy ((void *) pages, (const void *) other->pages, count * pages.item_size);
+    memcpy ((void *) page_map, (const void *) other->page_map, count * page_map.item_size);
+  }
+
+  bool is_equal (const hb_set_t *other) const
+  {
+    if (get_population () != other->get_population ())
+      return false;
+
+    unsigned int na = pages.length;
+    unsigned int nb = other->pages.length;
+
+    unsigned int a = 0, b = 0;
+    for (; a < na && b < nb; )
+    {
+      if (page_at (a).is_empty ()) { a++; continue; }
+      if (other->page_at (b).is_empty ()) { b++; continue; }
+      if (page_map[a].major != other->page_map[b].major ||
+          !page_at (a).is_equal (&other->page_at (b)))
+        return false;
+      a++;
+      b++;
+    }
+    for (; a < na; a++)
+      if (!page_at (a).is_empty ()) { return false; }
+    for (; b < nb; b++)
+      if (!other->page_at (b).is_empty ()) { return false; }
+
+    return true;
+  }
+
+  bool is_subset (const hb_set_t *larger_set) const
+  {
+    if (get_population () > larger_set->get_population ())
+      return false;
+
+    /* TODO Optimize to use pages. */
+    hb_codepoint_t c = INVALID;
+    while (next (&c))
+      if (!larger_set->has (c))
+        return false;
+
+    return true;
+  }
+
+  template <class Op>
+  void process (const hb_set_t *other)
+  {
+    if (unlikely (!successful)) return;
+
+    dirty ();
+
+    unsigned int na = pages.length;
+    unsigned int nb = other->pages.length;
+    unsigned int next_page = na;
+
+    unsigned int count = 0, newCount = 0;
+    unsigned int a = 0, b = 0;
+    for (; a < na && b < nb; )
+    {
+      if (page_map[a].major == other->page_map[b].major)
+      {
+        count++;
+        a++;
+        b++;
+      }
+      else if (page_map[a].major < other->page_map[b].major)
+      {
+        if (Op::passthru_left)
+          count++;
+        a++;
+      }
+      else
+      {
+        if (Op::passthru_right)
+          count++;
+        b++;
+      }
+    }
+    if (Op::passthru_left)
+      count += na - a;
+    if (Op::passthru_right)
+      count += nb - b;
+
+    if (count > pages.length)
+      if (!resize (count))
+        return;
+    newCount = count;
+
+    /* Process in-place backward. */
+    a = na;
+    b = nb;
+    for (; a && b; )
+    {
+      if (page_map[a - 1].major == other->page_map[b - 1].major)
+      {
+        a--;
+        b--;
+        count--;
+        page_map[count] = page_map[a];
+        Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
+      }
+      else if (page_map[a - 1].major > other->page_map[b - 1].major)
+      {
+        a--;
+        if (Op::passthru_left)
+        {
+          count--;
+          page_map[count] = page_map[a];
+        }
+      }
+      else
+      {
+        b--;
+        if (Op::passthru_right)
+        {
+          count--;
+          page_map[count].major = other->page_map[b].major;
+          page_map[count].index = next_page++;
+          page_at (count).v = other->page_at (b).v;
+        }
+      }
+    }
+    if (Op::passthru_left)
+      while (a)
+      {
+        a--;
+        count--;
+        page_map[count] = page_map [a];
+      }
+    if (Op::passthru_right)
+      while (b)
+      {
+        b--;
+        count--;
+        page_map[count].major = other->page_map[b].major;
+        page_map[count].index = next_page++;
+        page_at (count).v = other->page_at (b).v;
+      }
+    assert (!count);
+    if (pages.length > newCount)
+      resize (newCount);
+  }
+
+  void union_ (const hb_set_t *other)
+  {
+    process<HbOpOr> (other);
+  }
+  void intersect (const hb_set_t *other)
+  {
+    process<HbOpAnd> (other);
+  }
+  void subtract (const hb_set_t *other)
+  {
+    process<HbOpMinus> (other);
+  }
+  void symmetric_difference (const hb_set_t *other)
+  {
+    process<HbOpXor> (other);
+  }
+  bool next (hb_codepoint_t *codepoint) const
+  {
+    if (unlikely (*codepoint == INVALID)) {
+      *codepoint = get_min ();
+      return *codepoint != INVALID;
+    }
+
+    page_map_t map = {get_major (*codepoint), 0};
+    unsigned int i;
+    page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
+    if (i < page_map.length && page_map[i].major == map.major)
+    {
+      if (pages[page_map[i].index].next (codepoint))
+      {
+        *codepoint += page_map[i].major * page_t::PAGE_BITS;
+        return true;
+      }
+      i++;
+    }
+    for (; i < page_map.length; i++)
+    {
+      hb_codepoint_t m = pages[page_map[i].index].get_min ();
+      if (m != INVALID)
+      {
+        *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+        return true;
+      }
+    }
+    *codepoint = INVALID;
+    return false;
+  }
+  bool previous (hb_codepoint_t *codepoint) const
+  {
+    if (unlikely (*codepoint == INVALID)) {
+      *codepoint = get_max ();
+      return *codepoint != INVALID;
+    }
+
+    page_map_t map = {get_major (*codepoint), 0};
+    unsigned int i;
+    page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST);
+    if (i < page_map.length && page_map[i].major == map.major)
+    {
+      if (pages[page_map[i].index].previous (codepoint))
+      {
+        *codepoint += page_map[i].major * page_t::PAGE_BITS;
+        return true;
+      }
+    }
+    i--;
+    for (; (int) i >= 0; i--)
+    {
+      hb_codepoint_t m = pages[page_map[i].index].get_max ();
+      if (m != INVALID)
+      {
+        *codepoint = page_map[i].major * page_t::PAGE_BITS + m;
+        return true;
+      }
+    }
+    *codepoint = INVALID;
+    return false;
+  }
+  bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    hb_codepoint_t i;
+
+    i = *last;
+    if (!next (&i))
+    {
+      *last = *first = INVALID;
+      return false;
+    }
+
+    /* TODO Speed up. */
+    *last = *first = i;
+    while (next (&i) && i == *last + 1)
+      (*last)++;
+
+    return true;
+  }
+  bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
+  {
+    hb_codepoint_t i;
+
+    i = *first;
+    if (!previous (&i))
+    {
+      *last = *first = INVALID;
+      return false;
+    }
+
+    /* TODO Speed up. */
+    *last = *first = i;
+    while (previous (&i) && i == *first - 1)
+      (*first)--;
+
+    return true;
+  }
+
+  unsigned int get_population () const
+  {
+    if (population != (unsigned int) -1)
+      return population;
+
+    unsigned int pop = 0;
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      pop += pages[i].get_population ();
+
+    population = pop;
+    return pop;
+  }
+  hb_codepoint_t get_min () const
+  {
+    unsigned int count = pages.length;
+    for (unsigned int i = 0; i < count; i++)
+      if (!page_at (i).is_empty ())
+        return page_map[i].major * page_t::PAGE_BITS + page_at (i).get_min ();
+    return INVALID;
+  }
+  hb_codepoint_t get_max () const
+  {
+    unsigned int count = pages.length;
+    for (int i = count - 1; i >= 0; i++)
+      if (!page_at (i).is_empty ())
+        return page_map[(unsigned) i].major * page_t::PAGE_BITS + page_at (i).get_max ();
+    return INVALID;
+  }
+
+  static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
+
+  /*
+   * Iterator implementation.
+   */
+  struct const_iter_t : hb_sorted_iter_t<const_iter_t, const hb_codepoint_t>
+  {
+    const_iter_t (const hb_set_t &s_) :
+      s (s_), v (INVALID), l (s.get_population () + 1) { __next__ (); }
+
+    typedef hb_codepoint_t __item_type__;
+    hb_codepoint_t __item__ () const { return v; }
+    bool __more__ () const { return v != INVALID; }
+    void __next__ () { s.next (&v); if (l) l--; }
+    void __prev__ () { s.previous (&v); }
+    unsigned __len__ () { return l; }
+
+    protected:
+    const hb_set_t &s;
+    hb_codepoint_t v;
+    unsigned l;
+  };
+  const_iter_t const_iter () const { return const_iter_t (*this); }
+  operator const_iter_t () const { return const_iter (); }
+  typedef const_iter_t iter_t;
+  iter_t iter () const { return const_iter (); }
+
+  protected:
+
+  page_t *page_for_insert (hb_codepoint_t g)
+  {
+    page_map_t map = {get_major (g), pages.length};
+    unsigned int i;
+    if (!page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST))
+    {
+      if (!resize (pages.length + 1))
+        return nullptr;
+
+      pages[map.index].init0 ();
+      memmove (page_map + i + 1,
+               page_map + i,
+               (page_map.length - 1 - i) * page_map.item_size);
+      page_map[i] = map;
+    }
+    return &pages[page_map[i].index];
+  }
+  page_t *page_for (hb_codepoint_t g)
+  {
+    page_map_t key = {get_major (g)};
+    const page_map_t *found = page_map.bsearch (key);
+    if (found)
+      return &pages[found->index];
+    return nullptr;
+  }
+  const page_t *page_for (hb_codepoint_t g) const
+  {
+    page_map_t key = {get_major (g)};
+    const page_map_t *found = page_map.bsearch (key);
+    if (found)
+      return &pages[found->index];
+    return nullptr;
+  }
+  page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
+  const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
+  unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
+  hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
+};
+
+
+#endif /* HB_SET_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPE_PLAN_PRIVATE_HH
-#define HB_SHAPE_PLAN_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-#include "hb-shaper-private.hh"
-
-
-struct hb_shape_plan_t
-{
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_bool_t default_shaper_list;
-  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
-  hb_segment_properties_t props;
-
-  hb_shape_func_t *shaper_func;
-  const char *shaper_name;
-
-  hb_feature_t *user_features;
-  unsigned int num_user_features;
-
-  int *coords;
-  unsigned int num_coords;
-
-  struct hb_shaper_data_t shaper_data;
-};
-
-#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
-        , const hb_feature_t *user_features \
-        , unsigned int        num_user_features \
-        , const int          *coords \
-        , unsigned int        num_coords
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
-
-#endif /* HB_SHAPE_PLAN_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,55 +24,81 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
+#include "hb.hh"
+#include "hb-shape-plan.hh"
+#include "hb-shaper.hh"
+#include "hb-font.hh"
+#include "hb-buffer.hh"
+
+
+/**
+ * SECTION:hb-shape-plan
+ * @title: hb-shape-plan
+ * @short_description: Object representing a shaping plan
+ * @include: hb.h
+ *
+ * Shape plans are not used for shaping directly, but can be access to query
+ * certain information about how shaping will perform given a set of input
+ * parameters (script, language, direction, features, etc.)
+ * Most client would not need to deal with shape plans directly.
+ **/
 
 
-static void
-hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
-                    const hb_feature_t *user_features,
-                    unsigned int        num_user_features,
-                    const int          *coords,
-                    unsigned int        num_coords,
-                    const char * const *shaper_list)
+/*
+ * hb_shape_plan_key_t
+ */
+
+bool
+hb_shape_plan_key_t::init (bool                           copy,
+                           hb_face_t                     *face,
+                           const hb_segment_properties_t *props,
+                           const hb_feature_t            *user_features,
+                           unsigned int                   num_user_features,
+                           const int                     *coords,
+                           unsigned int                   num_coords,
+                           const char * const            *shaper_list)
 {
-  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
-                  "num_features=%d num_coords=%d shaper_list=%p",
-                  num_user_features,
-                  num_coords,
-                  shaper_list);
+  hb_feature_t *features = nullptr;
+  if (copy && num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
+    goto bail;
 
-  const hb_shaper_pair_t *shapers = _hb_shapers_get ();
+  this->props = *props;
+  this->num_user_features = num_user_features;
+  this->user_features = copy ? features : user_features;
+  if (copy && num_user_features)
+  {
+    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+    /* Make start/end uniform to easier catch bugs. */
+    for (unsigned int i = 0; i < num_user_features; i++)
+    {
+      if (features[0].start != HB_FEATURE_GLOBAL_START)
+        features[0].start = 1;
+      if (features[0].end   != HB_FEATURE_GLOBAL_END)
+        features[0].end   = 2;
+    }
+  }
+  this->shaper_func = nullptr;
+  this->shaper_name = nullptr;
+  this->ot.init (face, coords, num_coords);
+
+  /*
+   * Choose shaper.
+   */
 
 #define HB_SHAPER_PLAN(shaper) \
         HB_STMT_START { \
-          if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \
-            HB_SHAPER_DATA (shaper, shape_plan) = \
-              HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \
-                                                               user_features, num_user_features, \
-                                                               coords, num_coords); \
-            shape_plan->shaper_func = _hb_##shaper##_shape; \
-            shape_plan->shaper_name = #shaper; \
-            return; \
+          if (face->data.shaper) \
+          { \
+            this->shaper_func = _hb_##shaper##_shape; \
+            this->shaper_name = #shaper; \
+            return true; \
           } \
         } HB_STMT_END
 
-  if (likely (!shaper_list)) {
-    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
-      if (0)
-        ;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (shapers[i].func == _hb_##shaper##_shape) \
-        HB_SHAPER_PLAN (shaper);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  } else {
+  if (unlikely (shaper_list))
+  {
     for (; *shaper_list; shaper_list++)
-      if (0)
+      if (false)
         ;
 #define HB_SHAPER_IMPLEMENT(shaper) \
       else if (0 == strcmp (*shaper_list, #shaper)) \
@@ -80,8 +106,50 @@
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
   }
+  else
+  {
+    const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
+      if (false)
+        ;
+#define HB_SHAPER_IMPLEMENT(shaper) \
+      else if (shapers[i].func == _hb_##shaper##_shape) \
+        HB_SHAPER_PLAN (shaper);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+#undef HB_SHAPER_PLAN
 
-#undef HB_SHAPER_PLAN
+bail:
+  ::free (features);
+  return false;
+}
+
+bool
+hb_shape_plan_key_t::user_features_match (const hb_shape_plan_key_t *other)
+{
+  if (this->num_user_features != other->num_user_features)
+    return false;
+  for (unsigned int i = 0; i < num_user_features; i++)
+  {
+    if (this->user_features[i].tag   != other->user_features[i].tag   ||
+        this->user_features[i].value != other->user_features[i].value ||
+        (this->user_features[i].start == HB_FEATURE_GLOBAL_START &&
+         this->user_features[i].end   == HB_FEATURE_GLOBAL_END) !=
+        (other->user_features[i].start == HB_FEATURE_GLOBAL_START &&
+         other->user_features[i].end   == HB_FEATURE_GLOBAL_END))
+      return false;
+  }
+  return true;
+}
+
+bool
+hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other)
+{
+  return hb_segment_properties_equal (&this->props, &other->props) &&
+         this->user_features_match (other) &&
+         this->ot.equal (&other->ot) &&
+         this->shaper_func == other->shaper_func;
 }
 
 
@@ -89,6 +157,7 @@
  * hb_shape_plan_t
  */
 
+
 /**
  * hb_shape_plan_create: (Xconstructor)
  * @face:
@@ -121,7 +190,7 @@
                        const hb_segment_properties_t *props,
                        const hb_feature_t            *user_features,
                        unsigned int                   num_user_features,
-                       const int                     *orig_coords,
+                       const int                     *coords,
                        unsigned int                   num_coords,
                        const char * const            *shaper_list)
 {
@@ -132,49 +201,40 @@
                   num_coords,
                   shaper_list);
 
+  assert (props->direction != HB_DIRECTION_INVALID);
+
   hb_shape_plan_t *shape_plan;
-  hb_feature_t *features = nullptr;
-  int *coords = nullptr;
+
+  if (unlikely (!props))
+    goto bail;
+  if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
+    goto bail;
 
   if (unlikely (!face))
     face = hb_face_get_empty ();
-  if (unlikely (!props))
-    return hb_shape_plan_get_empty ();
-  if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
-    return hb_shape_plan_get_empty ();
-  if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
-  {
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
-  if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
-  {
-    free (coords);
-    free (features);
-    return hb_shape_plan_get_empty ();
-  }
-
-  assert (props->direction != HB_DIRECTION_INVALID);
+  hb_face_make_immutable (face);
+  shape_plan->face_unsafe = face;
 
-  hb_face_make_immutable (face);
-  shape_plan->default_shaper_list = !shaper_list;
-  shape_plan->face_unsafe = face;
-  shape_plan->props = *props;
-  shape_plan->num_user_features = num_user_features;
-  shape_plan->user_features = features;
-  if (num_user_features)
-    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
-  shape_plan->num_coords = num_coords;
-  shape_plan->coords = coords;
-  if (num_coords)
-    memcpy (coords, orig_coords, num_coords * sizeof (int));
-
-  hb_shape_plan_plan (shape_plan,
-                      user_features, num_user_features,
-                      coords, num_coords,
-                      shaper_list);
+  if (unlikely (!shape_plan->key.init (true,
+                                       face,
+                                       props,
+                                       user_features,
+                                       num_user_features,
+                                       coords,
+                                       num_coords,
+                                       shaper_list)))
+    goto bail2;
+  if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key)))
+    goto bail3;
 
   return shape_plan;
+
+bail3:
+  shape_plan->key.free ();
+bail2:
+  free (shape_plan);
+bail:
+  return hb_shape_plan_get_empty ();
 }
 
 /**
@@ -187,32 +247,9 @@
  * Since: 0.9.7
  **/
 hb_shape_plan_t *
-hb_shape_plan_get_empty (void)
+hb_shape_plan_get_empty ()
 {
-  static const hb_shape_plan_t _hb_shape_plan_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* default_shaper_list */
-    nullptr, /* face */
-    HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
-
-    nullptr, /* shaper_func */
-    nullptr, /* shaper_name */
-
-    nullptr, /* user_features */
-    0,    /* num_user_featurs */
-
-    nullptr, /* coords */
-    0,    /* num_coords */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_shape_plan_t *> (&_hb_shape_plan_nil);
+  return const_cast<hb_shape_plan_t *> (&Null(hb_shape_plan_t));
 }
 
 /**
@@ -244,13 +281,8 @@
 {
   if (!hb_object_destroy (shape_plan)) return;
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, shape_plan);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-  free (shape_plan->user_features);
-  free (shape_plan->coords);
-
+  shape_plan->ot.fini ();
+  shape_plan->key.free ();
   free (shape_plan);
 }
 
@@ -296,6 +328,22 @@
   return hb_object_get_user_data (shape_plan, key);
 }
 
+/**
+ * hb_shape_plan_get_shaper:
+ * @shape_plan: a shape plan.
+ *
+ *
+ *
+ * Return value: (transfer none):
+ *
+ * Since: 0.9.7
+ **/
+const char *
+hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
+{
+  return shape_plan->key.shaper_name;
+}
+
 
 /**
  * hb_shape_plan_execute:
@@ -321,32 +369,31 @@
   DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
                   "num_features=%d shaper_func=%p, shaper_name=%s",
                   num_features,
-                  shape_plan->shaper_func,
-                  shape_plan->shaper_name);
+                  shape_plan->key.shaper_func,
+                  shape_plan->key.shaper_name);
 
   if (unlikely (!buffer->len))
     return true;
 
-  assert (!hb_object_is_inert (buffer));
+  assert (!hb_object_is_immutable (buffer));
   assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
 
   if (unlikely (hb_object_is_inert (shape_plan)))
     return false;
 
   assert (shape_plan->face_unsafe == font->face);
-  assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props));
+  assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props));
 
 #define HB_SHAPER_EXECUTE(shaper) \
         HB_STMT_START { \
-          return HB_SHAPER_DATA (shaper, shape_plan) && \
-                 hb_##shaper##_shaper_font_data_ensure (font) && \
+          return font->data.shaper && \
                  _hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
         } HB_STMT_END
 
-  if (0)
+  if (false)
     ;
 #define HB_SHAPER_IMPLEMENT(shaper) \
-  else if (shape_plan->shaper_func == _hb_##shaper##_shape) \
+  else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \
     HB_SHAPER_EXECUTE (shaper);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
@@ -358,91 +405,8 @@
 
 
 /*
- * caching
- */
-
-#if 0
-static unsigned int
-hb_shape_plan_hash (const hb_shape_plan_t *shape_plan)
-{
-  return hb_segment_properties_hash (&shape_plan->props) +
-         shape_plan->default_shaper_list ? 0 : (intptr_t) shape_plan->shaper_func;
-}
-#endif
-
-/* User-feature caching is currently somewhat dumb:
- * it only finds matches where the feature array is identical,
- * not cases where the feature lists would be compatible for plan purposes
- * but have different ranges, for example.
+ * Caching
  */
-struct hb_shape_plan_proposal_t
-{
-  const hb_segment_properties_t  props;
-  const char * const            *shaper_list;
-  const hb_feature_t            *user_features;
-  unsigned int                   num_user_features;
-  const int                     *coords;
-  unsigned int                   num_coords;
-  hb_shape_func_t               *shaper_func;
-};
-
-static inline hb_bool_t
-hb_shape_plan_user_features_match (const hb_shape_plan_t          *shape_plan,
-                                   const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_user_features != shape_plan->num_user_features)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++)
-    if (proposal->user_features[i].tag   != shape_plan->user_features[i].tag   ||
-        proposal->user_features[i].value != shape_plan->user_features[i].value ||
-        proposal->user_features[i].start != shape_plan->user_features[i].start ||
-        proposal->user_features[i].end   != shape_plan->user_features[i].end)
-      return false;
-  return true;
-}
-
-static inline hb_bool_t
-hb_shape_plan_coords_match (const hb_shape_plan_t          *shape_plan,
-                            const hb_shape_plan_proposal_t *proposal)
-{
-  if (proposal->num_coords != shape_plan->num_coords)
-    return false;
-  for (unsigned int i = 0, n = proposal->num_coords; i < n; i++)
-    if (proposal->coords[i] != shape_plan->coords[i])
-      return false;
-  return true;
-}
-
-static hb_bool_t
-hb_shape_plan_matches (const hb_shape_plan_t          *shape_plan,
-                       const hb_shape_plan_proposal_t *proposal)
-{
-  return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
-         hb_shape_plan_user_features_match (shape_plan, proposal) &&
-         hb_shape_plan_coords_match (shape_plan, proposal) &&
-         ((shape_plan->default_shaper_list && !proposal->shaper_list) ||
-          (shape_plan->shaper_func == proposal->shaper_func));
-}
-
-static inline hb_bool_t
-hb_non_global_user_features_present (const hb_feature_t *user_features,
-                                     unsigned int        num_user_features)
-{
-  while (num_user_features) {
-    if (user_features->start != 0 || user_features->end != (unsigned int) -1)
-      return true;
-    num_user_features--;
-    user_features++;
-  }
-  return false;
-}
-
-static inline hb_bool_t
-hb_coords_present (const int *coords,
-                   unsigned int num_coords)
-{
-  return num_coords != 0;
-}
 
 /**
  * hb_shape_plan_create_cached:
@@ -486,62 +450,38 @@
                   num_user_features,
                   shaper_list);
 
-  hb_shape_plan_proposal_t proposal = {
-    *props,
-    shaper_list,
-    user_features,
-    num_user_features,
-    nullptr
-  };
+retry:
+  hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
+
+  bool dont_cache = hb_object_is_inert (face);
 
-  if (shaper_list) {
-    /* Choose shaper.  Adapted from hb_shape_plan_plan().
-     * Must choose shaper exactly the same way as that function. */
-    for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
-      if (0)
-        ;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (0 == strcmp (*shaper_item, #shaper) && \
-               hb_##shaper##_shaper_face_data_ensure (face)) \
-      { \
-        proposal.shaper_func = _hb_##shaper##_shape; \
-        break; \
-      }
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  if (likely (!dont_cache))
+  {
+    hb_shape_plan_key_t key;
+    if (!key.init (false,
+                   face,
+                   props,
+                   user_features,
+                   num_user_features,
+                   coords,
+                   num_coords,
+                   shaper_list))
+      return hb_shape_plan_get_empty ();
 
-    if (unlikely (!proposal.shaper_func))
-      return hb_shape_plan_get_empty ();
-  }
-
-
-retry:
-  hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atomic_ptr_get (&face->shape_plans);
-
-  /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */
-  if (!hb_coords_present (coords, num_coords))
     for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
-      if (hb_shape_plan_matches (node->shape_plan, &proposal))
+      if (node->shape_plan->key.equal (&key))
       {
         DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
         return hb_shape_plan_reference (node->shape_plan);
       }
+  }
 
-  /* Not found. */
   hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props,
                                                        user_features, num_user_features,
                                                        coords, num_coords,
                                                        shaper_list);
 
-  /* Don't add to the cache if face is inert. */
-  if (unlikely (hb_object_is_inert (face)))
-    return shape_plan;
-
-  /* Don't add the plan to the cache if there were user features with non-global ranges */
-  if (hb_non_global_user_features_present (user_features, num_user_features))
-    return shape_plan;
-  /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */
-  if (hb_coords_present (coords, num_coords))
+  if (unlikely (dont_cache))
     return shape_plan;
 
   hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t));
@@ -551,7 +491,8 @@
   node->shape_plan = shape_plan;
   node->next = cached_plan_nodes;
 
-  if (!hb_atomic_ptr_cmpexch (&face->shape_plans, cached_plan_nodes, node)) {
+  if (unlikely (!face->shape_plans.cmpexch (cached_plan_nodes, node)))
+  {
     hb_shape_plan_destroy (shape_plan);
     free (node);
     goto retry;
@@ -560,19 +501,3 @@
 
   return hb_shape_plan_reference (shape_plan);
 }
-
-/**
- * hb_shape_plan_get_shaper:
- * @shape_plan: a shape plan.
- *
- *
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.7
- **/
-const char *
-hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
-{
-  return shape_plan->shaper_name;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape-plan.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2012,2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SHAPE_PLAN_HH
+#define HB_SHAPE_PLAN_HH
+
+#include "hb.hh"
+#include "hb-shaper.hh"
+#include "hb-ot-shape.hh"
+
+
+struct hb_shape_plan_key_t
+{
+  hb_segment_properties_t  props;
+
+  const hb_feature_t      *user_features;
+  unsigned int             num_user_features;
+
+  hb_ot_shape_plan_key_t   ot;
+
+  hb_shape_func_t         *shaper_func;
+  const char              *shaper_name;
+
+  HB_INTERNAL inline bool init (bool                           copy,
+                                hb_face_t                     *face,
+                                const hb_segment_properties_t *props,
+                                const hb_feature_t            *user_features,
+                                unsigned int                   num_user_features,
+                                const int                     *coords,
+                                unsigned int                   num_coords,
+                                const char * const            *shaper_list);
+
+  HB_INTERNAL inline void free () { ::free ((void *) user_features); }
+
+  HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other);
+
+  HB_INTERNAL bool equal (const hb_shape_plan_key_t *other);
+};
+
+struct hb_shape_plan_t
+{
+  hb_object_header_t header;
+  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
+  hb_shape_plan_key_t key;
+  hb_ot_shape_plan_t ot;
+};
+
+
+#endif /* HB_SHAPE_PLAN_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shape.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -26,40 +26,70 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-buffer-private.hh"
-#include "hb-font-private.hh"
+#include "hb-shaper.hh"
+#include "hb-shape-plan.hh"
+#include "hb-buffer.hh"
+#include "hb-font.hh"
+#include "hb-machinery.hh"
+
 
 /**
  * SECTION:hb-shape
- * @title: Shaping
+ * @title: hb-shape
  * @short_description: Conversion of text strings into positioned glyphs
  * @include: hb.h
  *
  * Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
  * which are sequences of Unicode characters that use the same font and have
- * the same text direction, script and language. After shaping the buffer
+ * the same text direction, script, and language. After shaping the buffer
  * contains the output glyphs and their positions.
  **/
 
-static const char **static_shaper_list;
+
+#if HB_USE_ATEXIT
+static void free_static_shaper_list ();
+#endif
 
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shaper_list (void)
+static const char *nil_shaper_list[] = {nullptr};
+
+static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
+                                                              hb_shaper_list_lazy_loader_t>
 {
-retry:
-  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
-  if (!hb_atomic_ptr_cmpexch (&static_shaper_list, shaper_list, nullptr))
-    goto retry;
+  static const char ** create ()
+  {
+    const char **shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
+    if (unlikely (!shaper_list))
+      return nullptr;
+
+    const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+    unsigned int i;
+    for (i = 0; i < HB_SHAPERS_COUNT; i++)
+      shaper_list[i] = shapers[i].name;
+    shaper_list[i] = nullptr;
 
-  free (shaper_list);
+#if HB_USE_ATEXIT
+    atexit (free_static_shaper_list);
+#endif
+
+    return shaper_list;
+  }
+  static void destroy (const char **l)
+  { free (l); }
+  static const char ** get_null ()
+  { return nil_shaper_list; }
+} static_shaper_list;
+
+#if HB_USE_ATEXIT
+static
+void free_static_shaper_list ()
+{
+  static_shaper_list.free_instance ();
 }
 #endif
 
+
 /**
  * hb_shape_list_shapers:
  *
@@ -71,37 +101,9 @@
  * Since: 0.9.2
  **/
 const char **
-hb_shape_list_shapers (void)
+hb_shape_list_shapers ()
 {
-retry:
-  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
-
-  if (unlikely (!shaper_list))
-  {
-    /* Not found; allocate one. */
-    shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
-    if (unlikely (!shaper_list)) {
-      static const char *nil_shaper_list[] = {nullptr};
-      return nil_shaper_list;
-    }
-
-    const hb_shaper_pair_t *shapers = _hb_shapers_get ();
-    unsigned int i;
-    for (i = 0; i < HB_SHAPERS_COUNT; i++)
-      shaper_list[i] = shapers[i].name;
-    shaper_list[i] = nullptr;
-
-    if (!hb_atomic_ptr_cmpexch (&static_shaper_list, nullptr, shaper_list)) {
-      free (shaper_list);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_shaper_list); /* First person registers atexit() callback. */
-#endif
-  }
-
-  return shaper_list;
+  return static_shaper_list.get_unconst ();
 }
 
 
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-impl-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_IMPL_PRIVATE_HH
-#define HB_SHAPER_IMPL_PRIVATE_HH
-
-#include "hb-private.hh"
-
-#include "hb-shaper-private.hh"
-#include "hb-shape-plan-private.hh"
-#include "hb-font-private.hh"
-#include "hb-buffer-private.hh"
-
-
-#ifdef HB_SHAPER
-#define HB_SHAPER_DATA_GET(object) HB_SHAPER_DATA (HB_SHAPER, object)
-#endif
-
-
-#endif /* HB_SHAPER_IMPL_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-impl.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SHAPER_IMPL_HH
+#define HB_SHAPER_IMPL_HH
+
+#include "hb.hh"
+
+#include "hb-shaper.hh"
+#include "hb-face.hh"
+#include "hb-font.hh"
+#include "hb-shape-plan.hh"
+#include "hb-buffer.hh"
+
+#endif /* HB_SHAPER_IMPL_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-list.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-list.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -34,14 +34,8 @@
 /* Only picks up fonts that have a "Silf" table. */
 HB_SHAPER_IMPLEMENT (graphite2)
 #endif
-#ifdef HAVE_CORETEXT
-/* Only picks up fonts that have a "mort" or "morx" table. */
-HB_SHAPER_IMPLEMENT (coretext_aat)
-#endif
 
-#ifdef HAVE_OT
 HB_SHAPER_IMPLEMENT (ot) /* <--- This is our main OpenType shaper. */
-#endif
 
 #ifdef HAVE_UNISCRIBE
 HB_SHAPER_IMPLEMENT (uniscribe)
@@ -51,6 +45,10 @@
 #endif
 #ifdef HAVE_CORETEXT
 HB_SHAPER_IMPLEMENT (coretext)
+
+/* Only picks up fonts that have a "mort" or "morx" table.
+   Probably going to be removed https://github.com/harfbuzz/harfbuzz/issues/1478 */
+HB_SHAPER_IMPLEMENT (coretext_aat)
 #endif
 
 #ifdef HAVE_FALLBACK
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright © 2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_SHAPER_PRIVATE_HH
-#define HB_SHAPER_PRIVATE_HH
-
-#include "hb-private.hh"
-
-typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
-                                   hb_font_t          *font,
-                                   hb_buffer_t        *buffer,
-                                   const hb_feature_t *features,
-                                   unsigned int        num_features);
-
-#define HB_SHAPER_IMPLEMENT(name) \
-        extern "C" HB_INTERNAL hb_shape_func_t _hb_##name##_shape;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-struct hb_shaper_pair_t {
-  char name[16];
-  hb_shape_func_t *func;
-};
-
-HB_INTERNAL const hb_shaper_pair_t *
-_hb_shapers_get (void);
-
-
-/* For embedding in face / font / ... */
-struct hb_shaper_data_t {
-#define HB_SHAPER_IMPLEMENT(shaper) void *shaper;
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-};
-
-#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
-
-/* Means: succeeded, but don't need to keep any data. */
-#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
-
-/* Means: tried but failed to create. */
-#define HB_SHAPER_DATA_INVALID ((void *) -1)
-#define HB_SHAPER_DATA_IS_INVALID(data) ((void *) (data) == HB_SHAPER_DATA_INVALID)
-
-#define HB_SHAPER_DATA_TYPE_NAME(shaper, object)        hb_##shaper##_shaper_##object##_data_t
-#define HB_SHAPER_DATA_TYPE(shaper, object)             struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
-#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance)       (* (HB_SHAPER_DATA_TYPE(shaper, object) **) &(instance)->shaper_data.shaper)
-#define HB_SHAPER_DATA(shaper, object)                  HB_SHAPER_DATA_INSTANCE(shaper, object, object)
-#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)      _hb_##shaper##_shaper_##object##_data_create
-#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)     _hb_##shaper##_shaper_##object##_data_destroy
-#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object)      hb_##shaper##_shaper_##object##_data_ensure
-
-#define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \
-        HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
-        extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
-        HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \
-        extern "C" HB_INTERNAL void \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \
-        extern "C" HB_INTERNAL bool \
-        HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
-
-#define HB_SHAPER_DATA_DESTROY(shaper, object) \
-    if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object)) \
-      if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \
-        HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, true)
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, condition) \
-bool \
-HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
-{\
-  retry: \
-  HB_SHAPER_DATA_TYPE (shaper, object) *data = (HB_SHAPER_DATA_TYPE (shaper, object) *) hb_atomic_ptr_get (&HB_SHAPER_DATA (shaper, object)); \
-  if (likely (data) && !(condition)) { \
-    /* Drop and recreate. */ \
-    /* If someone dropped it in the mean time, throw it away and don't touch it. \
-     * Otherwise, destruct it. */ \
-    if (hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), data, nullptr)) { \
-      HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
-    } \
-    goto retry; \
-  } \
-  if (unlikely (!data)) { \
-    data = HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (object); \
-    if (unlikely (!data)) \
-      data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
-    if (!hb_atomic_ptr_cmpexch (&HB_SHAPER_DATA (shaper, object), nullptr, data)) { \
-      if (data && \
-          data != HB_SHAPER_DATA_INVALID && \
-          data != HB_SHAPER_DATA_SUCCEEDED) \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
-      goto retry; \
-    } \
-  } \
-  return data != nullptr && !HB_SHAPER_DATA_IS_INVALID (data); \
-}
-
-
-#endif /* HB_SHAPER_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,63 +24,41 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
-#include "hb-shaper-private.hh"
-#include "hb-atomic-private.hh"
+#include "hb.hh"
+#include "hb-shaper.hh"
+#include "hb-machinery.hh"
 
 
-static const hb_shaper_pair_t all_shapers[] = {
+static const hb_shaper_entry_t all_shapers[] = {
 #define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape},
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 };
 
-
-/* Thread-safe, lock-free, shapers */
-
-static const hb_shaper_pair_t *static_shapers;
-
-#ifdef HB_USE_ATEXIT
-static
-void free_static_shapers (void)
-{
-retry:
-  hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
-  if (!hb_atomic_ptr_cmpexch (&static_shapers, shapers, nullptr))
-    goto retry;
-
-  if (unlikely (shapers != all_shapers))
-    free ((void *) shapers);
-}
+#if HB_USE_ATEXIT
+static void free_static_shapers ();
 #endif
 
-const hb_shaper_pair_t *
-_hb_shapers_get (void)
+static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_t,
+                                                          hb_shapers_lazy_loader_t>
 {
-retry:
-  hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
-
-  if (unlikely (!shapers))
+  static hb_shaper_entry_t *create ()
   {
     char *env = getenv ("HB_SHAPER_LIST");
-    if (!env || !*env) {
-      (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
-      return (const hb_shaper_pair_t *) all_shapers;
-    }
+    if (!env || !*env)
+      return nullptr;
 
-    /* Not found; allocate one. */
-    shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers));
-    if (unlikely (!shapers)) {
-      (void) hb_atomic_ptr_cmpexch (&static_shapers, nullptr, &all_shapers[0]);
-      return (const hb_shaper_pair_t *) all_shapers;
-    }
+    hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) calloc (1, sizeof (all_shapers));
+    if (unlikely (!shapers))
+      return nullptr;
 
     memcpy (shapers, all_shapers, sizeof (all_shapers));
 
      /* Reorder shaper list to prefer requested shapers. */
     unsigned int i = 0;
     char *end, *p = env;
-    for (;;) {
+    for (;;)
+    {
       end = strchr (p, ',');
       if (!end)
         end = p + strlen (p);
@@ -90,7 +68,7 @@
             0 == strncmp (shapers[j].name, p, end - p))
         {
           /* Reorder this shaper to position i */
-         struct hb_shaper_pair_t t = shapers[j];
+         struct hb_shaper_entry_t t = shapers[j];
          memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
          shapers[i] = t;
          i++;
@@ -102,15 +80,26 @@
         p = end + 1;
     }
 
-    if (!hb_atomic_ptr_cmpexch (&static_shapers, nullptr, shapers)) {
-      free (shapers);
-      goto retry;
-    }
+#if HB_USE_ATEXIT
+    atexit (free_static_shapers);
+#endif
+
+    return shapers;
+  }
+  static void destroy (const hb_shaper_entry_t *p) { free ((void *) p); }
+  static const hb_shaper_entry_t *get_null ()      { return all_shapers; }
+} static_shapers;
 
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_shapers); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+static
+void free_static_shapers ()
+{
+  static_shapers.free_instance ();
+}
 #endif
-  }
 
-  return shapers;
+const hb_shaper_entry_t *
+_hb_shapers_get ()
+{
+  return static_shapers.get_unconst ();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-shaper.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,134 @@
+/*
+ * Copyright © 2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_SHAPER_HH
+#define HB_SHAPER_HH
+
+#include "hb.hh"
+#include "hb-machinery.hh"
+
+typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
+                                   hb_font_t          *font,
+                                   hb_buffer_t        *buffer,
+                                   const hb_feature_t *features,
+                                   unsigned int        num_features);
+
+#define HB_SHAPER_IMPLEMENT(name) \
+        extern "C" HB_INTERNAL hb_shape_func_t _hb_##name##_shape;
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
+struct hb_shaper_entry_t {
+  char name[16];
+  hb_shape_func_t *func;
+};
+
+HB_INTERNAL const hb_shaper_entry_t *
+_hb_shapers_get ();
+
+
+template <typename Data, unsigned int WheresData, typename T>
+struct hb_shaper_lazy_loader_t;
+
+#define HB_SHAPER_ORDER(Shaper) \
+  HB_PASTE (HB_SHAPER_ORDER_, Shaper)
+enum hb_shaper_order_t
+{
+  _HB_SHAPER_ORDER_ORDER_ZERO,
+#define HB_SHAPER_IMPLEMENT(Shaper) \
+      HB_SHAPER_ORDER (Shaper),
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  _HB_SHAPERS_COUNT_PLUS_ONE,
+  HB_SHAPERS_COUNT = _HB_SHAPERS_COUNT_PLUS_ONE - 1,
+};
+
+template <enum hb_shaper_order_t order, typename Object> struct hb_shaper_object_data_type_t;
+
+#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
+#define HB_SHAPER_DATA_TYPE(shaper, object)             hb_##shaper##_##object##_data_t
+#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)      _hb_##shaper##_shaper_##object##_data_create
+#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)     _hb_##shaper##_shaper_##object##_data_destroy
+
+#define HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, object) \
+        \
+        struct HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
+        extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
+        HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object); \
+        extern "C" HB_INTERNAL void \
+        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *shaper##_##object); \
+        \
+        template <> \
+        struct hb_shaper_object_data_type_t<HB_SHAPER_ORDER (shaper), hb_##object##_t> \
+        { \
+          typedef HB_SHAPER_DATA_TYPE(shaper, object) value; \
+        }; \
+        \
+        template <unsigned int WheresData> \
+        struct hb_shaper_lazy_loader_t<hb_##object##_t, WheresData, HB_SHAPER_DATA_TYPE(shaper, object)> \
+                : hb_lazy_loader_t<HB_SHAPER_DATA_TYPE(shaper, object), \
+                                   hb_shaper_lazy_loader_t<hb_##object##_t, \
+                                                           WheresData, \
+                                                           HB_SHAPER_DATA_TYPE(shaper, object)>, \
+                                   hb_##object##_t, WheresData> \
+        { \
+          typedef HB_SHAPER_DATA_TYPE(shaper, object) Type; \
+          static Type* create (hb_##object##_t *data) \
+          { return HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (data); } \
+          static Type *get_null () { return nullptr; } \
+          static void destroy (Type *p) { HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (p); } \
+        }; \
+        \
+        static_assert (true, "") /* Require semicolon. */
+
+
+template <typename Object>
+struct hb_shaper_object_dataset_t
+{
+  void init0 (Object *parent_data)
+  {
+    this->parent_data = parent_data;
+#define HB_SHAPER_IMPLEMENT(shaper) shaper.init0 ();
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+  void fini ()
+  {
+#define HB_SHAPER_IMPLEMENT(shaper) shaper.fini ();
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+
+  Object *parent_data; /* MUST be JUST before the lazy loaders. */
+#define HB_SHAPER_IMPLEMENT(shaper) \
+        hb_shaper_lazy_loader_t<Object, HB_SHAPER_ORDER(shaper), \
+                                typename hb_shaper_object_data_type_t<HB_SHAPER_ORDER(shaper), Object>::value \
+                               > shaper;
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+};
+
+#endif /* HB_SHAPER_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-static.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-static.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,9 +24,52 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+#include "hb-open-type.hh"
+#include "hb-face.hh"
+
+#include "hb-aat-layout-common.hh"
+#include "hb-aat-layout-feat-table.hh"
+#include "hb-ot-layout-common.hh"
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-head-table.hh"
+#include "hb-ot-maxp-table.hh"
 
 #ifndef HB_NO_VISIBILITY
-void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
-/*thread_local*/ void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {};
+
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
+
+DEFINE_NULL_NAMESPACE_BYTES (OT, Index) =  {0xFF,0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
+DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
+/* Hand-coded because Lookup is a template.  Sad. */
+const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
+
+
+unsigned int
+hb_face_t::load_num_glyphs () const
+{
+  hb_sanitize_context_t c = hb_sanitize_context_t ();
+  c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
+  hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
+  const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
+
+  unsigned int ret = maxp_table->get_num_glyphs ();
+  num_glyphs.set_relaxed (ret);
+  hb_blob_destroy (maxp_blob);
+  return ret;
+}
+
+unsigned int
+hb_face_t::load_upem () const
+{
+  unsigned int ret = table.head->get_upem ();
+  upem.set_relaxed (ret);
+  return ret;
+}
+
 #endif
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-string-array.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-string-array.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -29,7 +29,7 @@
 #define HB_STRING_ARRAY_HH
 #endif
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 /* Based on Bruno Haible's code in Appendix B of Ulrich Drepper's dsohowto.pdf:
  * https://software.intel.com/sites/default/files/m/a/1/e/dsohowto.pdf */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff-common.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,226 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-ot-cff-common.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-subset-cff-common.hh"
+
+/* Disable FDSelect format 0 for compatibility with fonttools which doesn't seem choose it.
+ * Rarely any/much smaller than format 3 anyway. */
+#define CFF_SERIALIZE_FDSELECT_0  0
+
+using namespace CFF;
+
+/**
+ * hb_plan_subset_cff_fdselect
+ * Determine an optimal FDSelect format according to a provided plan.
+ *
+ * Return value: FDSelect format, size, and ranges for the most compact subset FDSelect
+ * along with a font index remapping table
+ **/
+
+bool
+hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
+                            unsigned int fdCount,
+                            const FDSelect &src, /* IN */
+                            unsigned int &subset_fd_count /* OUT */,
+                            unsigned int &subset_fdselect_size /* OUT */,
+                            unsigned int &subset_fdselect_format /* OUT */,
+                            hb_vector_t<code_pair_t> &fdselect_ranges /* OUT */,
+                            remap_t &fdmap /* OUT */)
+{
+  subset_fd_count = 0;
+  subset_fdselect_size = 0;
+  subset_fdselect_format = 0;
+  unsigned int  num_ranges = 0;
+
+  unsigned int subset_num_glyphs = glyphs.length;
+  if (subset_num_glyphs == 0)
+    return true;
+
+  {
+    /* use hb_set to determine the subset of font dicts */
+    hb_set_t  *set = hb_set_create ();
+    if (set == &Null (hb_set_t))
+      return false;
+    hb_codepoint_t  prev_fd = CFF_UNDEF_CODE;
+    for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
+    {
+      hb_codepoint_t  fd = src.get_fd (glyphs[i]);
+      set->add (fd);
+
+      if (fd != prev_fd)
+      {
+        num_ranges++;
+        prev_fd = fd;
+        code_pair_t pair = { fd, i };
+        fdselect_ranges.push (pair);
+      }
+    }
+
+    subset_fd_count = set->get_population ();
+    if (subset_fd_count == fdCount)
+    {
+      /* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
+      fdmap.identity (fdCount);
+      hb_set_destroy (set);
+    }
+    else
+    {
+      /* create a fdmap */
+      if (!fdmap.reset (fdCount))
+      {
+        hb_set_destroy (set);
+        return false;
+      }
+
+      hb_codepoint_t  fd = CFF_UNDEF_CODE;
+      while (set->next (&fd))
+        fdmap.add (fd);
+      hb_set_destroy (set);
+      if (unlikely (fdmap.get_count () != subset_fd_count))
+        return false;
+    }
+
+    /* update each font dict index stored as "code" in fdselect_ranges */
+    for (unsigned int i = 0; i < fdselect_ranges.length; i++)
+      fdselect_ranges[i].code = fdmap[fdselect_ranges[i].code];
+  }
+
+  /* determine which FDSelect format is most compact */
+  if (subset_fd_count > 0xFF)
+  {
+    if (unlikely (src.format != 4))
+      return false;
+    subset_fdselect_format = 4;
+    subset_fdselect_size = FDSelect::min_size + FDSelect4::min_size + FDSelect4_Range::static_size * num_ranges + HBUINT32::static_size;
+  }
+  else
+  {
+#if CFF_SERIALIZE_FDSELECT_0
+    unsigned int format0_size = FDSelect::min_size + FDSelect0::min_size + HBUINT8::static_size * subset_num_glyphs;
+#endif
+    unsigned int format3_size = FDSelect::min_size + FDSelect3::min_size + FDSelect3_Range::static_size * num_ranges + HBUINT16::static_size;
+
+#if CFF_SERIALIZE_FDSELECT_0
+    if (format0_size <= format3_size)
+    {
+      // subset_fdselect_format = 0;
+      subset_fdselect_size = format0_size;
+    }
+    else
+#endif
+    {
+      subset_fdselect_format = 3;
+      subset_fdselect_size = format3_size;
+    }
+  }
+
+  return true;
+}
+
+template <typename FDSELECT3_4>
+static inline bool
+serialize_fdselect_3_4 (hb_serialize_context_t *c,
+                          const unsigned int num_glyphs,
+                          const FDSelect &src,
+                          unsigned int size,
+                          const hb_vector_t<code_pair_t> &fdselect_ranges)
+{
+  TRACE_SERIALIZE (this);
+  FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
+  if (unlikely (p == nullptr)) return_trace (false);
+  p->nRanges ().set (fdselect_ranges.length);
+  for (unsigned int i = 0; i < fdselect_ranges.length; i++)
+  {
+    p->ranges[i].first.set (fdselect_ranges[i].glyph);
+    p->ranges[i].fd.set (fdselect_ranges[i].code);
+  }
+  p->sentinel().set (num_glyphs);
+  return_trace (true);
+}
+
+/**
+ * hb_serialize_cff_fdselect
+ * Serialize a subset FDSelect format planned above.
+ **/
+bool
+hb_serialize_cff_fdselect (hb_serialize_context_t *c,
+                          const unsigned int num_glyphs,
+                          const FDSelect &src,
+                          unsigned int fd_count,
+                          unsigned int fdselect_format,
+                          unsigned int size,
+                          const hb_vector_t<code_pair_t> &fdselect_ranges)
+{
+  TRACE_SERIALIZE (this);
+  FDSelect  *p = c->allocate_min<FDSelect> ();
+  if (unlikely (p == nullptr)) return_trace (false);
+  p->format.set (fdselect_format);
+  size -= FDSelect::min_size;
+
+  switch (fdselect_format)
+  {
+#if CFF_SERIALIZE_FDSELECT_0
+    case 0:
+    {
+      FDSelect0 *p = c->allocate_size<FDSelect0> (size);
+      if (unlikely (p == nullptr)) return_trace (false);
+      unsigned int range_index = 0;
+      unsigned int  fd = fdselect_ranges[range_index++].code;
+      for (unsigned int i = 0; i < num_glyphs; i++)
+      {
+        if ((range_index < fdselect_ranges.len) &&
+            (i >= fdselect_ranges[range_index].glyph))
+        {
+          fd = fdselect_ranges[range_index++].code;
+        }
+        p->fds[i].set (fd);
+      }
+      break;
+    }
+#endif /* CFF_SERIALIZE_FDSELECT_0 */
+
+    case 3:
+      return serialize_fdselect_3_4<FDSelect3> (c,
+                                                num_glyphs,
+                                                src,
+                                                size,
+                                                fdselect_ranges);
+
+    case 4:
+      return serialize_fdselect_3_4<FDSelect4> (c,
+                                                num_glyphs,
+                                                src,
+                                                size,
+                                                fdselect_ranges);
+
+    default:
+      assert(false);
+  }
+
+  return_trace (true);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff-common.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,990 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_SUBSET_CFF_COMMON_HH
+#define HB_SUBSET_CFF_COMMON_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+#include "hb-cff-interp-cs-common.hh"
+
+namespace CFF {
+
+/* Used for writing a temporary charstring */
+struct str_encoder_t
+{
+  str_encoder_t (str_buff_t &buff_)
+    : buff (buff_), error (false) {}
+
+  void reset () { buff.resize (0); }
+
+  void encode_byte (unsigned char b)
+  {
+    if (unlikely (buff.push (b) == &Crap(unsigned char)))
+      set_error ();
+  }
+
+  void encode_int (int v)
+  {
+    if ((-1131 <= v) && (v <= 1131))
+    {
+      if ((-107 <= v) && (v <= 107))
+        encode_byte (v + 139);
+      else if (v > 0)
+      {
+        v -= 108;
+        encode_byte ((v >> 8) + OpCode_TwoBytePosInt0);
+        encode_byte (v & 0xFF);
+      }
+      else
+      {
+        v = -v - 108;
+        encode_byte ((v >> 8) + OpCode_TwoByteNegInt0);
+        encode_byte (v & 0xFF);
+      }
+    }
+    else
+    {
+      if (unlikely (v < -32768))
+        v = -32768;
+      else if (unlikely (v > 32767))
+        v = 32767;
+      encode_byte (OpCode_shortint);
+      encode_byte ((v >> 8) & 0xFF);
+      encode_byte (v & 0xFF);
+    }
+  }
+
+  void encode_num (const number_t& n)
+  {
+    if (n.in_int_range ())
+    {
+      encode_int (n.to_int ());
+    }
+    else
+    {
+      int32_t v = n.to_fixed ();
+      encode_byte (OpCode_fixedcs);
+      encode_byte ((v >> 24) & 0xFF);
+      encode_byte ((v >> 16) & 0xFF);
+      encode_byte ((v >> 8) & 0xFF);
+      encode_byte (v & 0xFF);
+    }
+  }
+
+  void encode_op (op_code_t op)
+  {
+    if (Is_OpCode_ESC (op))
+    {
+      encode_byte (OpCode_escape);
+      encode_byte (Unmake_OpCode_ESC (op));
+    }
+    else
+      encode_byte (op);
+  }
+
+  void copy_str (const byte_str_t &str)
+  {
+    unsigned int  offset = buff.length;
+    buff.resize (offset + str.length);
+    if (unlikely (buff.length < offset + str.length))
+    {
+      set_error ();
+      return;
+    }
+    memcpy (&buff[offset], &str[0], str.length);
+  }
+
+  bool is_error () const { return error; }
+
+  protected:
+  void set_error () { error = true; }
+
+  str_buff_t &buff;
+  bool    error;
+};
+
+struct cff_sub_table_offsets_t {
+  cff_sub_table_offsets_t () : privateDictsOffset (0)
+  {
+    topDictInfo.init ();
+    FDSelectInfo.init ();
+    FDArrayInfo.init ();
+    charStringsInfo.init ();
+    globalSubrsInfo.init ();
+    localSubrsInfos.init ();
+  }
+
+  ~cff_sub_table_offsets_t () { localSubrsInfos.fini (); }
+
+  table_info_t     topDictInfo;
+  table_info_t     FDSelectInfo;
+  table_info_t     FDArrayInfo;
+  table_info_t     charStringsInfo;
+  unsigned int  privateDictsOffset;
+  table_info_t     globalSubrsInfo;
+  hb_vector_t<table_info_t>  localSubrsInfos;
+};
+
+template <typename OPSTR=op_str_t>
+struct cff_top_dict_op_serializer_t : op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const OPSTR &opstr,
+                  const cff_sub_table_offsets_t &offsets) const
+  {
+    TRACE_SERIALIZE (this);
+
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+        return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.charStringsInfo.offset));
+
+      case OpCode_FDArray:
+        return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.FDArrayInfo.offset));
+
+      case OpCode_FDSelect:
+        return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.FDSelectInfo.offset));
+
+      default:
+        return_trace (copy_opstr (c, opstr));
+    }
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (const OPSTR &opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_CharStrings:
+      case OpCode_FDArray:
+      case OpCode_FDSelect:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+        return opstr.str.length;
+    }
+  }
+};
+
+struct cff_font_dict_op_serializer_t : op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const op_str_t &opstr,
+                  const table_info_t &privateDictInfo) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (opstr.op == OpCode_Private)
+    {
+      /* serialize the private dict size & offset as 2-byte & 4-byte integers */
+      if (unlikely (!UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) ||
+                    !UnsizedByteStr::serialize_int4 (c, privateDictInfo.offset)))
+        return_trace (false);
+
+      /* serialize the opcode */
+      HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+      if (unlikely (p == nullptr)) return_trace (false);
+      p->set (OpCode_Private);
+
+      return_trace (true);
+    }
+    else
+    {
+      HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+      if (unlikely (d == nullptr)) return_trace (false);
+      memcpy (d, &opstr.str[0], opstr.str.length);
+    }
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    if (opstr.op == OpCode_Private)
+      return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
+    else
+      return opstr.str.length;
+  }
+};
+
+struct cff_private_dict_op_serializer_t : op_serializer_t
+{
+  cff_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_)
+    : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {}
+
+  bool serialize (hb_serialize_context_t *c,
+                  const op_str_t &opstr,
+                  const unsigned int subrsOffset) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+      return true;
+    if (opstr.op == OpCode_Subrs)
+    {
+      if (desubroutinize || (subrsOffset == 0))
+        return_trace (true);
+      else
+        return_trace (FontDict::serialize_offset2_op (c, opstr.op, subrsOffset));
+    }
+    else
+      return_trace (copy_opstr (c, opstr));
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr,
+                                          bool has_localsubr=true) const
+  {
+    if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
+      return 0;
+    if (opstr.op == OpCode_Subrs)
+    {
+      if (desubroutinize || !has_localsubr)
+        return 0;
+      else
+        return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (opstr.op);
+    }
+    else
+      return opstr.str.length;
+  }
+
+  protected:
+  const bool  desubroutinize;
+  const bool  drop_hints;
+};
+
+struct flatten_param_t
+{
+  str_buff_t     &flatStr;
+  bool  drop_hints;
+};
+
+template <typename ACC, typename ENV, typename OPSET>
+struct subr_flattener_t
+{
+  subr_flattener_t (const ACC &acc_,
+                    const hb_vector_t<hb_codepoint_t> &glyphs_,
+                    bool drop_hints_) : acc (acc_), glyphs (glyphs_),
+                                        drop_hints (drop_hints_) {}
+
+  bool flatten (str_buff_vec_t &flat_charstrings)
+  {
+    if (!flat_charstrings.resize (glyphs.length))
+      return false;
+    for (unsigned int i = 0; i < glyphs.length; i++)
+      flat_charstrings[i].init ();
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      hb_codepoint_t  glyph = glyphs[i];
+      const byte_str_t str = (*acc.charStrings)[glyph];
+      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      if (unlikely (fd >= acc.fdCount))
+        return false;
+      cs_interpreter_t<ENV, OPSET, flatten_param_t> interp;
+      interp.env.init (str, acc, fd);
+      flatten_param_t  param = { flat_charstrings[i], drop_hints };
+      if (unlikely (!interp.interpret (param)))
+        return false;
+    }
+    return true;
+  }
+
+  const ACC &acc;
+  const hb_vector_t<hb_codepoint_t> &glyphs;
+  bool  drop_hints;
+};
+
+struct subr_closures_t
+{
+  subr_closures_t () : valid (false), global_closure (nullptr)
+  { local_closures.init (); }
+
+  void init (unsigned int fd_count)
+  {
+    valid = true;
+    global_closure = hb_set_create ();
+    if (global_closure == hb_set_get_empty ())
+      valid = false;
+    if (!local_closures.resize (fd_count))
+      valid = false;
+
+    for (unsigned int i = 0; i < local_closures.length; i++)
+    {
+      local_closures[i] = hb_set_create ();
+      if (local_closures[i] == hb_set_get_empty ())
+        valid = false;
+    }
+  }
+
+  void fini ()
+  {
+    hb_set_destroy (global_closure);
+    for (unsigned int i = 0; i < local_closures.length; i++)
+      hb_set_destroy (local_closures[i]);
+    local_closures.fini ();
+  }
+
+  void reset ()
+  {
+    hb_set_clear (global_closure);
+    for (unsigned int i = 0; i < local_closures.length; i++)
+      hb_set_clear (local_closures[i]);
+  }
+
+  bool is_valid () const { return valid; }
+  bool  valid;
+  hb_set_t  *global_closure;
+  hb_vector_t<hb_set_t *> local_closures;
+};
+
+struct parsed_cs_op_t : op_str_t
+{
+  void init (unsigned int subr_num_ = 0)
+  {
+    op_str_t::init ();
+    subr_num = subr_num_;
+    drop_flag = false;
+    keep_flag = false;
+    skip_flag = false;
+  }
+
+  void fini () { op_str_t::fini (); }
+
+  bool for_drop () const { return drop_flag; }
+  void set_drop ()       { if (!for_keep ()) drop_flag = true; }
+
+  bool for_keep () const { return keep_flag; }
+  void set_keep ()       { keep_flag = true; }
+
+  bool for_skip () const { return skip_flag; }
+  void set_skip ()       { skip_flag = true; }
+
+  unsigned int  subr_num;
+
+  protected:
+  bool    drop_flag : 1;
+  bool    keep_flag : 1;
+  bool    skip_flag : 1;
+};
+
+struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
+{
+  void init ()
+  {
+    SUPER::init ();
+    parsed = false;
+    hint_dropped = false;
+    has_prefix_ = false;
+  }
+
+  void add_op (op_code_t op, const byte_str_ref_t& str_ref)
+  {
+    if (!is_parsed ())
+      SUPER::add_op (op, str_ref);
+  }
+
+  void add_call_op (op_code_t op, const byte_str_ref_t& str_ref, unsigned int subr_num)
+  {
+    if (!is_parsed ())
+    {
+      unsigned int parsed_len = get_count ();
+      if (likely (parsed_len > 0))
+        values[parsed_len-1].set_skip ();
+
+      parsed_cs_op_t val;
+      val.init (subr_num);
+      SUPER::add_op (op, str_ref, val);
+    }
+  }
+
+  void set_prefix (const number_t &num, op_code_t op = OpCode_Invalid)
+  {
+    has_prefix_ = true;
+    prefix_op_ = op;
+    prefix_num_ = num;
+  }
+
+  bool at_end (unsigned int pos) const
+  {
+    return ((pos + 1 >= values.length) /* CFF2 */
+        || (values[pos + 1].op == OpCode_return));
+  }
+
+  bool is_parsed () const { return parsed; }
+  void set_parsed ()      { parsed = true; }
+
+  bool is_hint_dropped () const { return hint_dropped; }
+  void set_hint_dropped ()      { hint_dropped = true; }
+
+  bool is_vsindex_dropped () const { return vsindex_dropped; }
+  void set_vsindex_dropped ()      { vsindex_dropped = true; }
+
+  bool has_prefix () const          { return has_prefix_; }
+  op_code_t prefix_op () const         { return prefix_op_; }
+  const number_t &prefix_num () const { return prefix_num_; }
+
+  protected:
+  bool    parsed;
+  bool    hint_dropped;
+  bool    vsindex_dropped;
+  bool    has_prefix_;
+  op_code_t     prefix_op_;
+  number_t      prefix_num_;
+
+  private:
+  typedef parsed_values_t<parsed_cs_op_t> SUPER;
+};
+
+struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
+{
+  void init (unsigned int len_ = 0)
+  {
+    SUPER::init ();
+    resize (len_);
+    for (unsigned int i = 0; i < length; i++)
+      (*this)[i].init ();
+  }
+  void fini () { SUPER::fini_deep (); }
+
+  private:
+  typedef hb_vector_t<parsed_cs_str_t> SUPER;
+};
+
+struct subr_subset_param_t
+{
+  void init (parsed_cs_str_t *parsed_charstring_,
+             parsed_cs_str_vec_t *parsed_global_subrs_, parsed_cs_str_vec_t *parsed_local_subrs_,
+             hb_set_t *global_closure_, hb_set_t *local_closure_,
+             bool drop_hints_)
+  {
+    parsed_charstring = parsed_charstring_;
+    current_parsed_str = parsed_charstring;
+    parsed_global_subrs = parsed_global_subrs_;
+    parsed_local_subrs = parsed_local_subrs_;
+    global_closure = global_closure_;
+    local_closure = local_closure_;
+    drop_hints = drop_hints_;
+  }
+
+  parsed_cs_str_t *get_parsed_str_for_context (call_context_t &context)
+  {
+    switch (context.type)
+    {
+      case CSType_CharString:
+        return parsed_charstring;
+
+      case CSType_LocalSubr:
+        if (likely (context.subr_num < parsed_local_subrs->length))
+          return &(*parsed_local_subrs)[context.subr_num];
+        break;
+
+      case CSType_GlobalSubr:
+        if (likely (context.subr_num < parsed_global_subrs->length))
+          return &(*parsed_global_subrs)[context.subr_num];
+        break;
+    }
+    return nullptr;
+  }
+
+  template <typename ENV>
+  void set_current_str (ENV &env, bool calling)
+  {
+    parsed_cs_str_t  *parsed_str = get_parsed_str_for_context (env.context);
+    if (likely (parsed_str != nullptr))
+    {
+      /* If the called subroutine is parsed partially but not completely yet,
+       * it must be because we are calling it recursively.
+       * Handle it as an error. */
+      if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
+        env.set_error ();
+      else
+        current_parsed_str = parsed_str;
+    }
+    else
+      env.set_error ();
+  }
+
+  parsed_cs_str_t       *current_parsed_str;
+
+  parsed_cs_str_t       *parsed_charstring;
+  parsed_cs_str_vec_t   *parsed_global_subrs;
+  parsed_cs_str_vec_t   *parsed_local_subrs;
+  hb_set_t      *global_closure;
+  hb_set_t      *local_closure;
+  bool    drop_hints;
+};
+
+struct subr_remap_t : remap_t
+{
+  void create (hb_set_t *closure)
+  {
+    /* create a remapping of subroutine numbers from old to new.
+     * no optimization based on usage counts. fonttools doesn't appear doing that either.
+     */
+    reset (closure->get_max () + 1);
+    for (hb_codepoint_t old_num = 0; old_num < length; old_num++)
+    {
+      if (hb_set_has (closure, old_num))
+        add (old_num);
+    }
+
+    if (get_count () < 1240)
+      bias = 107;
+    else if (get_count () < 33900)
+      bias = 1131;
+    else
+      bias = 32768;
+  }
+
+  hb_codepoint_t operator[] (unsigned int old_num) const
+  {
+    if (old_num >= length)
+      return CFF_UNDEF_CODE;
+    else
+      return remap_t::operator[] (old_num);
+  }
+
+  int biased_num (unsigned int old_num) const
+  {
+    hb_codepoint_t new_num = (*this)[old_num];
+    return (int)new_num - bias;
+  }
+
+  protected:
+  int bias;
+};
+
+struct subr_remap_ts
+{
+  subr_remap_ts ()
+  {
+    global_remap.init ();
+    local_remaps.init ();
+  }
+
+  ~subr_remap_ts () { fini (); }
+
+  void init (unsigned int fdCount)
+  {
+    local_remaps.resize (fdCount);
+    for (unsigned int i = 0; i < fdCount; i++)
+      local_remaps[i].init ();
+  }
+
+  void create (subr_closures_t& closures)
+  {
+    global_remap.create (closures.global_closure);
+    for (unsigned int i = 0; i < local_remaps.length; i++)
+      local_remaps[i].create (closures.local_closures[i]);
+  }
+
+  void fini ()
+  {
+    global_remap.fini ();
+    local_remaps.fini_deep ();
+  }
+
+  subr_remap_t         global_remap;
+  hb_vector_t<subr_remap_t>  local_remaps;
+};
+
+template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typename OPSET>
+struct subr_subsetter_t
+{
+  subr_subsetter_t ()
+  {
+    parsed_charstrings.init ();
+    parsed_global_subrs.init ();
+    parsed_local_subrs.init ();
+  }
+
+  ~subr_subsetter_t ()
+  {
+    closures.fini ();
+    remaps.fini ();
+    parsed_charstrings.fini_deep ();
+    parsed_global_subrs.fini_deep ();
+    parsed_local_subrs.fini_deep ();
+  }
+
+  /* Subroutine subsetting with --no-desubroutinize runs in phases:
+   *
+   * 1. execute charstrings/subroutines to determine subroutine closures
+   * 2. parse out all operators and numbers
+   * 3. mark hint operators and operands for removal if --no-hinting
+   * 4. re-encode all charstrings and subroutines with new subroutine numbers
+   *
+   * Phases #1 and #2 are done at the same time in collect_subrs ().
+   * Phase #3 walks charstrings/subroutines forward then backward (hence parsing required),
+   * because we can't tell if a number belongs to a hint op until we see the first moveto.
+   *
+   * Assumption: a callsubr/callgsubr operator must immediately follow a (biased) subroutine number
+   * within the same charstring/subroutine, e.g., not split across a charstring and a subroutine.
+   */
+  bool subset (ACC &acc, const hb_vector_t<hb_codepoint_t> &glyphs, bool drop_hints)
+  {
+    closures.init (acc.fdCount);
+    remaps.init (acc.fdCount);
+
+    parsed_charstrings.init (glyphs.length);
+    parsed_global_subrs.init (acc.globalSubrs->count);
+    parsed_local_subrs.resize (acc.fdCount);
+    for (unsigned int i = 0; i < acc.fdCount; i++)
+    {
+      parsed_local_subrs[i].init (acc.privateDicts[i].localSubrs->count);
+    }
+    if (unlikely (!closures.valid))
+      return false;
+
+    /* phase 1 & 2 */
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      hb_codepoint_t  glyph = glyphs[i];
+      const byte_str_t str = (*acc.charStrings)[glyph];
+      unsigned int fd = acc.fdSelect->get_fd (glyph);
+      if (unlikely (fd >= acc.fdCount))
+        return false;
+
+      cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp;
+      interp.env.init (str, acc, fd);
+
+      subr_subset_param_t  param;
+      param.init (&parsed_charstrings[i],
+                  &parsed_global_subrs,  &parsed_local_subrs[fd],
+                  closures.global_closure, closures.local_closures[fd],
+                  drop_hints);
+
+      if (unlikely (!interp.interpret (param)))
+        return false;
+
+      /* finalize parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
+      SUBSETTER::finalize_parsed_str (interp.env, param, parsed_charstrings[i]);
+    }
+
+    if (drop_hints)
+    {
+      /* mark hint ops and arguments for drop */
+      for (unsigned int i = 0; i < glyphs.length; i++)
+      {
+        unsigned int fd = acc.fdSelect->get_fd (glyphs[i]);
+        if (unlikely (fd >= acc.fdCount))
+          return false;
+        subr_subset_param_t  param;
+        param.init (&parsed_charstrings[i],
+                    &parsed_global_subrs,  &parsed_local_subrs[fd],
+                    closures.global_closure, closures.local_closures[fd],
+                    drop_hints);
+
+        drop_hints_param_t  drop;
+        if (drop_hints_in_str (parsed_charstrings[i], param, drop))
+        {
+          parsed_charstrings[i].set_hint_dropped ();
+          if (drop.vsindex_dropped)
+            parsed_charstrings[i].set_vsindex_dropped ();
+        }
+      }
+
+      /* after dropping hints recreate closures of actually used subrs */
+      closures.reset ();
+      for (unsigned int i = 0; i < glyphs.length; i++)
+      {
+        unsigned int fd = acc.fdSelect->get_fd (glyphs[i]);
+        if (unlikely (fd >= acc.fdCount))
+          return false;
+        subr_subset_param_t  param;
+        param.init (&parsed_charstrings[i],
+                    &parsed_global_subrs,  &parsed_local_subrs[fd],
+                    closures.global_closure, closures.local_closures[fd],
+                    drop_hints);
+        collect_subr_refs_in_str (parsed_charstrings[i], param);
+      }
+    }
+
+    remaps.create (closures);
+
+    return true;
+  }
+
+  bool encode_charstrings (ACC &acc, const hb_vector_t<hb_codepoint_t> &glyphs, str_buff_vec_t &buffArray) const
+  {
+    if (unlikely (!buffArray.resize (glyphs.length)))
+      return false;
+    for (unsigned int i = 0; i < glyphs.length; i++)
+    {
+      unsigned int  fd = acc.fdSelect->get_fd (glyphs[i]);
+      if (unlikely (fd >= acc.fdCount))
+        return false;
+      if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
+        return false;
+    }
+    return true;
+  }
+
+  bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const
+  {
+    unsigned int  count = remap.get_count ();
+
+    if (unlikely (!buffArray.resize (count)))
+      return false;
+    for (unsigned int old_num = 0; old_num < subrs.length; old_num++)
+    {
+      hb_codepoint_t new_num = remap[old_num];
+      if (new_num != CFF_UNDEF_CODE)
+      {
+        if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
+          return false;
+      }
+    }
+    return true;
+  }
+
+  bool encode_globalsubrs (str_buff_vec_t &buffArray)
+  {
+    return encode_subrs (parsed_global_subrs, remaps.global_remap, 0, buffArray);
+  }
+
+  bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const
+  {
+    return encode_subrs (parsed_local_subrs[fd], remaps.local_remaps[fd], fd, buffArray);
+  }
+
+  protected:
+  struct drop_hints_param_t
+  {
+    drop_hints_param_t ()
+      : seen_moveto (false),
+        ends_in_hint (false),
+        vsindex_dropped (false) {}
+
+    bool  seen_moveto;
+    bool  ends_in_hint;
+    bool  vsindex_dropped;
+  };
+
+  bool drop_hints_in_subr (parsed_cs_str_t &str, unsigned int pos,
+                           parsed_cs_str_vec_t &subrs, unsigned int subr_num,
+                           const subr_subset_param_t &param, drop_hints_param_t &drop)
+  {
+    drop.ends_in_hint = false;
+    bool has_hint = drop_hints_in_str (subrs[subr_num], param, drop);
+
+    /* if this subr ends with a stem hint (i.e., not a number a potential argument for moveto),
+     * then this entire subroutine must be a hint. drop its call. */
+    if (drop.ends_in_hint)
+    {
+      str.values[pos].set_drop ();
+      /* if this subr call is at the end of the parent subr, propagate the flag
+       * otherwise reset the flag */
+      if (!str.at_end (pos))
+        drop.ends_in_hint = false;
+    }
+
+    return has_hint;
+  }
+
+  /* returns true if it sees a hint op before the first moveto */
+  bool drop_hints_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param, drop_hints_param_t &drop)
+  {
+    bool  seen_hint = false;
+
+    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    {
+      bool  has_hint = false;
+      switch (str.values[pos].op)
+      {
+        case OpCode_callsubr:
+          has_hint = drop_hints_in_subr (str, pos,
+                                        *param.parsed_local_subrs, str.values[pos].subr_num,
+                                        param, drop);
+
+          break;
+
+        case OpCode_callgsubr:
+          has_hint = drop_hints_in_subr (str, pos,
+                                        *param.parsed_global_subrs, str.values[pos].subr_num,
+                                        param, drop);
+          break;
+
+        case OpCode_rmoveto:
+        case OpCode_hmoveto:
+        case OpCode_vmoveto:
+          drop.seen_moveto = true;
+          break;
+
+        case OpCode_hintmask:
+        case OpCode_cntrmask:
+          if (drop.seen_moveto)
+          {
+            str.values[pos].set_drop ();
+            break;
+          }
+          HB_FALLTHROUGH;
+
+        case OpCode_hstemhm:
+        case OpCode_vstemhm:
+        case OpCode_hstem:
+        case OpCode_vstem:
+          has_hint = true;
+          str.values[pos].set_drop ();
+          if (str.at_end (pos))
+            drop.ends_in_hint = true;
+          break;
+
+        case OpCode_dotsection:
+          str.values[pos].set_drop ();
+          break;
+
+        default:
+          /* NONE */
+          break;
+      }
+      if (has_hint)
+      {
+        for (int i = pos - 1; i >= 0; i--)
+        {
+          parsed_cs_op_t  &csop = str.values[(unsigned)i];
+          if (csop.for_drop ())
+            break;
+          csop.set_drop ();
+          if (csop.op == OpCode_vsindexcs)
+            drop.vsindex_dropped = true;
+        }
+        seen_hint |= has_hint;
+      }
+    }
+
+    return seen_hint;
+  }
+
+  void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos,
+                                  unsigned int subr_num, parsed_cs_str_vec_t &subrs,
+                                  hb_set_t *closure,
+                                  const subr_subset_param_t &param)
+  {
+    hb_set_add (closure, subr_num);
+    collect_subr_refs_in_str (subrs[subr_num], param);
+  }
+
+  void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t &param)
+  {
+    for (unsigned int pos = 0; pos < str.values.length; pos++)
+    {
+      if (!str.values[pos].for_drop ())
+      {
+        switch (str.values[pos].op)
+        {
+          case OpCode_callsubr:
+            collect_subr_refs_in_subr (str, pos,
+                                       str.values[pos].subr_num, *param.parsed_local_subrs,
+                                       param.local_closure, param);
+            break;
+
+          case OpCode_callgsubr:
+            collect_subr_refs_in_subr (str, pos,
+                                       str.values[pos].subr_num, *param.parsed_global_subrs,
+                                       param.global_closure, param);
+            break;
+
+          default: break;
+        }
+      }
+    }
+  }
+
+  bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
+  {
+    buff.init ();
+    str_encoder_t  encoder (buff);
+    encoder.reset ();
+    /* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
+     * re-insert it at the beginning of charstreing */
+    if (str.has_prefix () && str.is_hint_dropped ())
+    {
+      encoder.encode_num (str.prefix_num ());
+      if (str.prefix_op () != OpCode_Invalid)
+        encoder.encode_op (str.prefix_op ());
+    }
+    for (unsigned int i = 0; i < str.get_count(); i++)
+    {
+      const parsed_cs_op_t  &opstr = str.values[i];
+      if (!opstr.for_drop () && !opstr.for_skip ())
+      {
+        switch (opstr.op)
+        {
+          case OpCode_callsubr:
+            encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num));
+            encoder.encode_op (OpCode_callsubr);
+            break;
+
+          case OpCode_callgsubr:
+            encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num));
+            encoder.encode_op (OpCode_callgsubr);
+            break;
+
+          default:
+            encoder.copy_str (opstr.str);
+            break;
+        }
+      }
+    }
+    return !encoder.is_error ();
+  }
+
+  protected:
+  subr_closures_t             closures;
+
+  parsed_cs_str_vec_t          parsed_charstrings;
+  parsed_cs_str_vec_t          parsed_global_subrs;
+  hb_vector_t<parsed_cs_str_vec_t>  parsed_local_subrs;
+
+  subr_remap_ts         remaps;
+
+  private:
+  typedef typename SUBRS::count_type subr_count_type;
+};
+
+} /* namespace CFF */
+
+HB_INTERNAL bool
+hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
+                            unsigned int fdCount,
+                            const CFF::FDSelect &src, /* IN */
+                            unsigned int &subset_fd_count /* OUT */,
+                            unsigned int &subset_fdselect_size /* OUT */,
+                            unsigned int &subset_fdselect_format /* OUT */,
+                            hb_vector_t<CFF::code_pair_t> &fdselect_ranges /* OUT */,
+                            CFF::remap_t &fdmap /* OUT */);
+
+HB_INTERNAL bool
+hb_serialize_cff_fdselect (hb_serialize_context_t *c,
+                          unsigned int num_glyphs,
+                          const CFF::FDSelect &src,
+                          unsigned int fd_count,
+                          unsigned int fdselect_format,
+                          unsigned int size,
+                          const hb_vector_t<CFF::code_pair_t> &fdselect_ranges);
+
+#endif /* HB_SUBSET_CFF_COMMON_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff1.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,1103 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-set.h"
+#include "hb-subset-cff1.hh"
+#include "hb-subset-plan.hh"
+#include "hb-subset-cff-common.hh"
+#include "hb-cff1-interp-cs.hh"
+
+using namespace CFF;
+
+struct remap_sid_t : remap_t
+{
+  unsigned int add (unsigned int sid)
+  {
+    if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
+      return offset_sid (remap_t::add (unoffset_sid (sid)));
+    else
+      return sid;
+  }
+
+  unsigned int operator[] (unsigned int sid) const
+  {
+    if (is_std_std (sid) || (sid == CFF_UNDEF_SID))
+      return sid;
+    else
+      return offset_sid (remap_t::operator [] (unoffset_sid (sid)));
+  }
+
+  static const unsigned int num_std_strings = 391;
+
+  static bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
+  static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
+  static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
+};
+
+struct cff1_sub_table_offsets_t : cff_sub_table_offsets_t
+{
+  cff1_sub_table_offsets_t ()
+    : cff_sub_table_offsets_t (),
+      nameIndexOffset (0),
+      encodingOffset (0)
+  {
+    stringIndexInfo.init ();
+    charsetInfo.init ();
+    privateDictInfo.init ();
+  }
+
+  unsigned int  nameIndexOffset;
+  table_info_t  stringIndexInfo;
+  unsigned int  encodingOffset;
+  table_info_t  charsetInfo;
+  table_info_t  privateDictInfo;
+};
+
+/* a copy of a parsed out cff1_top_dict_values_t augmented with additional operators */
+struct cff1_top_dict_values_mod_t : cff1_top_dict_values_t
+{
+  void init (const cff1_top_dict_values_t *base_= &Null(cff1_top_dict_values_t))
+  {
+    SUPER::init ();
+    base = base_;
+  }
+
+  void fini () { SUPER::fini (); }
+
+  unsigned get_count () const { return base->get_count () + SUPER::get_count (); }
+  const cff1_top_dict_val_t &get_value (unsigned int i) const
+  {
+    if (i < base->get_count ())
+      return (*base)[i];
+    else
+      return SUPER::values[i - base->get_count ()];
+  }
+  const cff1_top_dict_val_t &operator [] (unsigned int i) const { return get_value (i); }
+
+  void reassignSIDs (const remap_sid_t& sidmap)
+  {
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+      nameSIDs[i] = sidmap[base->nameSIDs[i]];
+  }
+
+  protected:
+  typedef cff1_top_dict_values_t SUPER;
+  const cff1_top_dict_values_t *base;
+};
+
+struct top_dict_modifiers_t
+{
+  top_dict_modifiers_t (const cff1_sub_table_offsets_t &offsets_,
+                           const unsigned int (&nameSIDs_)[name_dict_values_t::ValCount])
+    : offsets (offsets_),
+      nameSIDs (nameSIDs_)
+  {}
+
+  const cff1_sub_table_offsets_t &offsets;
+  const unsigned int    (&nameSIDs)[name_dict_values_t::ValCount];
+};
+
+struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dict_val_t>
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const cff1_top_dict_val_t &opstr,
+                  const top_dict_modifiers_t &mod) const
+  {
+    TRACE_SERIALIZE (this);
+
+    op_code_t op = opstr.op;
+    switch (op)
+    {
+      case OpCode_charset:
+        return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.charsetInfo.offset));
+
+      case OpCode_Encoding:
+        return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.encodingOffset));
+
+      case OpCode_Private:
+        {
+          if (unlikely (!UnsizedByteStr::serialize_int2 (c, mod.offsets.privateDictInfo.size)))
+            return_trace (false);
+          if (unlikely (!UnsizedByteStr::serialize_int4 (c, mod.offsets.privateDictInfo.offset)))
+            return_trace (false);
+          HBUINT8 *p = c->allocate_size<HBUINT8> (1);
+          if (unlikely (p == nullptr)) return_trace (false);
+          p->set (OpCode_Private);
+        }
+        break;
+
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+      case OpCode_FontName:
+        return_trace (FontDict::serialize_offset2_op(c, op, mod.nameSIDs[name_dict_values_t::name_op_to_index (op)]));
+
+      case OpCode_ROS:
+        {
+          /* for registry & ordering, reassigned SIDs are serialized
+           * for supplement, the original byte string is copied along with the op code */
+          op_str_t supp_op;
+          supp_op.op = op;
+          if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
+            return_trace (false);
+          supp_op.str = byte_str_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+          return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
+                        UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
+                        copy_opstr (c, supp_op));
+        }
+      default:
+        return_trace (cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::serialize (c, opstr, mod.offsets));
+    }
+    return_trace (true);
+  }
+
+  unsigned int calculate_serialized_size (const cff1_top_dict_val_t &opstr) const
+  {
+    op_code_t op = opstr.op;
+    switch (op)
+    {
+      case OpCode_charset:
+      case OpCode_Encoding:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
+
+      case OpCode_Private:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
+
+      case OpCode_version:
+      case OpCode_Notice:
+      case OpCode_Copyright:
+      case OpCode_FullName:
+      case OpCode_FamilyName:
+      case OpCode_Weight:
+      case OpCode_PostScript:
+      case OpCode_BaseFontName:
+      case OpCode_FontName:
+        return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (op);
+
+      case OpCode_ROS:
+        return ((OpCode_Size (OpCode_shortint) + 2) * 2) + (opstr.str.length - opstr.last_arg_offset)/* supplement + op */;
+
+      default:
+        return cff_top_dict_op_serializer_t<cff1_top_dict_val_t>::calculate_serialized_size (opstr);
+    }
+  }
+};
+
+struct font_dict_values_mod_t
+{
+  void init (const cff1_font_dict_values_t *base_,
+             unsigned int fontName_,
+             const table_info_t &privateDictInfo_)
+  {
+    base = base_;
+    fontName = fontName_;
+    privateDictInfo = privateDictInfo_;
+  }
+
+  unsigned get_count () const { return base->get_count (); }
+
+  const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
+
+  const cff1_font_dict_values_t    *base;
+  table_info_t             privateDictInfo;
+  unsigned int          fontName;
+};
+
+struct cff1_font_dict_op_serializer_t : cff_font_dict_op_serializer_t
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const op_str_t &opstr,
+                  const font_dict_values_mod_t &mod) const
+  {
+    TRACE_SERIALIZE (this);
+
+    if (opstr.op == OpCode_FontName)
+      return_trace (FontDict::serialize_uint2_op (c, opstr.op, mod.fontName));
+    else
+      return_trace (SUPER::serialize (c, opstr, mod.privateDictInfo));
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    if (opstr.op == OpCode_FontName)
+      return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_FontName);
+    else
+      return SUPER::calculate_serialized_size (opstr);
+  }
+
+  private:
+  typedef cff_font_dict_op_serializer_t SUPER;
+};
+
+struct cff1_cs_opset_flatten_t : cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatten_param_t>
+{
+  static void flush_args_and_op (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    if (env.arg_start > 0)
+      flush_width (env, param);
+
+    switch (op)
+    {
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+      case OpCode_dotsection:
+        if (param.drop_hints)
+        {
+          env.clear_args ();
+          return;
+        }
+        HB_FALLTHROUGH;
+
+      default:
+        SUPER::flush_args_and_op (op, env, param);
+        break;
+    }
+  }
+  static void flush_args (cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    str_encoder_t  encoder (param.flatStr);
+    for (unsigned int i = env.arg_start; i < env.argStack.get_count (); i++)
+      encoder.encode_num (env.eval_arg (i));
+    SUPER::flush_args (env, param);
+  }
+
+  static void flush_op (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    str_encoder_t  encoder (param.flatStr);
+    encoder.encode_op (op);
+  }
+
+  static void flush_width (cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    assert (env.has_width);
+    str_encoder_t  encoder (param.flatStr);
+    encoder.encode_num (env.width);
+  }
+
+  static void flush_hintmask (op_code_t op, cff1_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    SUPER::flush_hintmask (op, env, param);
+    if (!param.drop_hints)
+    {
+      str_encoder_t  encoder (param.flatStr);
+      for (unsigned int i = 0; i < env.hintmask_size; i++)
+        encoder.encode_byte (env.str_ref[i]);
+    }
+  }
+
+  private:
+  typedef cff1_cs_opset_t<cff1_cs_opset_flatten_t, flatten_param_t> SUPER;
+};
+
+struct range_list_t : hb_vector_t<code_pair_t>
+{
+  /* replace the first glyph ID in the "glyph" field each range with a nLeft value */
+  bool finalize (unsigned int last_glyph)
+  {
+    bool  two_byte = false;
+    for (unsigned int i = (*this).length; i > 0; i--)
+    {
+      code_pair_t &pair = (*this)[i - 1];
+      unsigned int  nLeft = last_glyph - pair.glyph - 1;
+      if (nLeft >= 0x100)
+        two_byte = true;
+      last_glyph = pair.glyph;
+      pair.glyph = nLeft;
+    }
+    return two_byte;
+  }
+};
+
+struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t>
+{
+  static void process_op (op_code_t op, cff1_cs_interp_env_t &env, subr_subset_param_t& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+        param.current_parsed_str->add_op (op, env.str_ref);
+        param.current_parsed_str->set_parsed ();
+        env.returnFromSubr ();
+        param.set_current_str (env, false);
+        break;
+
+      case OpCode_endchar:
+        param.current_parsed_str->add_op (op, env.str_ref);
+        param.current_parsed_str->set_parsed ();
+        SUPER::process_op (op, env, param);
+        break;
+
+      case OpCode_callsubr:
+        process_call_subr (op, CSType_LocalSubr, env, param, env.localSubrs, param.local_closure);
+        break;
+
+      case OpCode_callgsubr:
+        process_call_subr (op, CSType_GlobalSubr, env, param, env.globalSubrs, param.global_closure);
+        break;
+
+      default:
+        SUPER::process_op (op, env, param);
+        param.current_parsed_str->add_op (op, env.str_ref);
+        break;
+    }
+  }
+
+  protected:
+  static void process_call_subr (op_code_t op, cs_type_t type,
+                                 cff1_cs_interp_env_t &env, subr_subset_param_t& param,
+                                 cff1_biased_subrs_t& subrs, hb_set_t *closure)
+  {
+    byte_str_ref_t    str_ref = env.str_ref;
+    env.callSubr (subrs, type);
+    param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
+    hb_set_add (closure, env.context.subr_num);
+    param.set_current_str (env, true);
+  }
+
+  private:
+  typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+};
+
+struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t>
+{
+  static void finalize_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+  {
+    /* insert width at the beginning of the charstring as necessary */
+    if (env.has_width)
+      charstring.set_prefix (env.width);
+
+    /* subroutines/charstring left on the call stack are legally left unmarked
+     * unmarked when a subroutine terminates with endchar. mark them.
+     */
+    param.current_parsed_str->set_parsed ();
+    for (unsigned int i = 0; i < env.callStack.get_count (); i++)
+    {
+      parsed_cs_str_t  *parsed_str = param.get_parsed_str_for_context (env.callStack[i]);
+      if (likely (parsed_str != nullptr))
+        parsed_str->set_parsed ();
+      else
+        env.set_error ();
+    }
+  }
+};
+
+struct cff_subset_plan {
+  cff_subset_plan ()
+    : final_size (0),
+      offsets (),
+      orig_fdcount (0),
+      subset_fdcount (1),
+      subset_fdselect_format (0),
+      drop_hints (false),
+      desubroutinize(false)
+  {
+    topdict_sizes.init ();
+    topdict_sizes.resize (1);
+    topdict_mod.init ();
+    subset_fdselect_ranges.init ();
+    fdmap.init ();
+    subset_charstrings.init ();
+    subset_globalsubrs.init ();
+    subset_localsubrs.init ();
+    fontdicts_mod.init ();
+    subset_enc_code_ranges.init ();
+    subset_enc_supp_codes.init ();
+    subset_charset_ranges.init ();
+    sidmap.init ();
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+      topDictModSIDs[i] = CFF_UNDEF_SID;
+  }
+
+  ~cff_subset_plan ()
+  {
+    topdict_sizes.fini ();
+    topdict_mod.fini ();
+    subset_fdselect_ranges.fini ();
+    fdmap.fini ();
+    subset_charstrings.fini_deep ();
+    subset_globalsubrs.fini_deep ();
+    subset_localsubrs.fini_deep ();
+    fontdicts_mod.fini ();
+    subset_enc_code_ranges.fini ();
+    subset_enc_supp_codes.fini ();
+    subset_charset_ranges.fini ();
+    sidmap.fini ();
+  }
+
+  unsigned int plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+  {
+    const Encoding *encoding = acc.encoding;
+    unsigned int  size0, size1, supp_size;
+    hb_codepoint_t  code, last_code = CFF_UNDEF_CODE;
+    hb_vector_t<hb_codepoint_t> supp_codes;
+
+    subset_enc_code_ranges.resize (0);
+    supp_size = 0;
+    supp_codes.init ();
+
+    subset_enc_num_codes = plan->glyphs.length - 1;
+    unsigned int glyph;
+    for (glyph = 1; glyph < plan->glyphs.length; glyph++)
+    {
+      hb_codepoint_t  orig_glyph = plan->glyphs[glyph];
+      code = acc.glyph_to_code (orig_glyph);
+      if (code == CFF_UNDEF_CODE)
+      {
+        subset_enc_num_codes = glyph - 1;
+        break;
+      }
+
+      if (code != last_code + 1)
+      {
+        code_pair_t pair = { code, glyph };
+        subset_enc_code_ranges.push (pair);
+      }
+      last_code = code;
+
+      if (encoding != &Null(Encoding))
+      {
+        hb_codepoint_t  sid = acc.glyph_to_sid (orig_glyph);
+        encoding->get_supplement_codes (sid, supp_codes);
+        for (unsigned int i = 0; i < supp_codes.length; i++)
+        {
+          code_pair_t pair = { supp_codes[i], sid };
+          subset_enc_supp_codes.push (pair);
+        }
+        supp_size += SuppEncoding::static_size * supp_codes.length;
+      }
+    }
+    supp_codes.fini ();
+
+    subset_enc_code_ranges.finalize (glyph);
+
+    assert (subset_enc_num_codes <= 0xFF);
+    size0 = Encoding0::min_size + HBUINT8::static_size * subset_enc_num_codes;
+    size1 = Encoding1::min_size + Encoding1_Range::static_size * subset_enc_code_ranges.length;
+
+    if (size0 < size1)
+      subset_enc_format = 0;
+    else
+      subset_enc_format = 1;
+
+    return Encoding::calculate_serialized_size (
+                        subset_enc_format,
+                        subset_enc_format? subset_enc_code_ranges.length: subset_enc_num_codes,
+                        subset_enc_supp_codes.length);
+  }
+
+  unsigned int plan_subset_charset (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
+  {
+    unsigned int  size0, size_ranges;
+    hb_codepoint_t  sid, last_sid = CFF_UNDEF_CODE;
+
+    subset_charset_ranges.resize (0);
+    unsigned int glyph;
+    for (glyph = 1; glyph < plan->glyphs.length; glyph++)
+    {
+      hb_codepoint_t  orig_glyph = plan->glyphs[glyph];
+      sid = acc.glyph_to_sid (orig_glyph);
+
+      if (!acc.is_CID ())
+        sid = sidmap.add (sid);
+
+      if (sid != last_sid + 1)
+      {
+        code_pair_t pair = { sid, glyph };
+        subset_charset_ranges.push (pair);
+      }
+      last_sid = sid;
+    }
+
+    bool two_byte = subset_charset_ranges.finalize (glyph);
+
+    size0 = Charset0::min_size + HBUINT16::static_size * (plan->glyphs.length - 1);
+    if (!two_byte)
+      size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length;
+    else
+      size_ranges = Charset2::min_size + Charset2_Range::static_size * subset_charset_ranges.length;
+
+    if (size0 < size_ranges)
+      subset_charset_format = 0;
+    else if (!two_byte)
+      subset_charset_format = 1;
+    else
+      subset_charset_format = 2;
+
+    return Charset::calculate_serialized_size (
+                        subset_charset_format,
+                        subset_charset_format? subset_charset_ranges.length: plan->glyphs.length);
+  }
+
+  bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
+  {
+    if (unlikely (!sidmap.reset (acc.stringIndex->count)))
+      return false;
+
+    for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
+    {
+      unsigned int sid = acc.topDict.nameSIDs[i];
+      if (sid != CFF_UNDEF_SID)
+      {
+        (void)sidmap.add (sid);
+        topDictModSIDs[i] = sidmap[sid];
+      }
+    }
+
+    if (acc.fdArray != &Null(CFF1FDArray))
+      for (unsigned int i = 0; i < orig_fdcount; i++)
+        if (fdmap.includes (i))
+          (void)sidmap.add (acc.fontDicts[i].fontName);
+
+    return true;
+  }
+
+  bool create (const OT::cff1::accelerator_subset_t &acc,
+                      hb_subset_plan_t *plan)
+  {
+     /* make sure notdef is first */
+    if ((plan->glyphs.length == 0) || (plan->glyphs[0] != 0)) return false;
+
+    final_size = 0;
+    num_glyphs = plan->glyphs.length;
+    orig_fdcount = acc.fdCount;
+    drop_hints = plan->drop_hints;
+    desubroutinize = plan->desubroutinize;
+
+    /* check whether the subset renumbers any glyph IDs */
+    gid_renum = false;
+    for (unsigned int glyph = 0; glyph < plan->glyphs.length; glyph++)
+    {
+      if (plan->glyphs[glyph] != glyph) {
+        gid_renum = true;
+        break;
+      }
+    }
+
+    subset_charset = gid_renum || !acc.is_predef_charset ();
+    subset_encoding = !acc.is_CID() && !acc.is_predef_encoding ();
+
+    /* CFF header */
+    final_size += OT::cff1::static_size;
+
+    /* Name INDEX */
+    offsets.nameIndexOffset = final_size;
+    final_size += acc.nameIndex->get_size ();
+
+    /* top dict INDEX */
+    {
+      /* Add encoding/charset to a (copy of) top dict as necessary */
+      topdict_mod.init (&acc.topDict);
+      bool need_to_add_enc = (subset_encoding && !acc.topDict.has_op (OpCode_Encoding));
+      bool need_to_add_set = (subset_charset && !acc.topDict.has_op (OpCode_charset));
+      if (need_to_add_enc || need_to_add_set)
+      {
+        if (need_to_add_enc)
+          topdict_mod.add_op (OpCode_Encoding);
+        if (need_to_add_set)
+          topdict_mod.add_op (OpCode_charset);
+      }
+      offsets.topDictInfo.offset = final_size;
+      cff1_top_dict_op_serializer_t topSzr;
+      unsigned int topDictSize = TopDict::calculate_serialized_size (topdict_mod, topSzr);
+      offsets.topDictInfo.offSize = calcOffSize(topDictSize);
+      if (unlikely (offsets.topDictInfo.offSize > 4))
+        return false;
+      final_size += CFF1IndexOf<TopDict>::calculate_serialized_size<cff1_top_dict_values_mod_t>
+                                                (offsets.topDictInfo.offSize,
+                                                 &topdict_mod, 1, topdict_sizes, topSzr);
+    }
+
+    /* Determine re-mapping of font index as fdmap among other info */
+    if (acc.fdSelect != &Null(CFF1FDSelect))
+    {
+        if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
+                                  orig_fdcount,
+                                  *acc.fdSelect,
+                                  subset_fdcount,
+                                  offsets.FDSelectInfo.size,
+                                  subset_fdselect_format,
+                                  subset_fdselect_ranges,
+                                  fdmap)))
+        return false;
+    }
+    else
+      fdmap.identity (1);
+
+    /* remove unused SIDs & reassign SIDs */
+    {
+      /* SIDs for name strings in dicts are added before glyph names so they fit in 16-bit int range */
+      if (unlikely (!collect_sids_in_dicts (acc)))
+        return false;
+      if (unlikely (sidmap.get_count () > 0x8000))      /* assumption: a dict won't reference that many strings */
+        return false;
+      if (subset_charset)
+        offsets.charsetInfo.size = plan_subset_charset (acc, plan);
+
+      topdict_mod.reassignSIDs (sidmap);
+    }
+
+    /* String INDEX */
+    {
+      offsets.stringIndexInfo.offset = final_size;
+      offsets.stringIndexInfo.size = acc.stringIndex->calculate_serialized_size (offsets.stringIndexInfo.offSize, sidmap);
+      final_size += offsets.stringIndexInfo.size;
+    }
+
+    if (desubroutinize)
+    {
+      /* Flatten global & local subrs */
+      subr_flattener_t<const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_flatten_t>
+                    flattener(acc, plan->glyphs, plan->drop_hints);
+      if (!flattener.flatten (subset_charstrings))
+        return false;
+
+      /* no global/local subroutines */
+      offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (1, 0, 0);
+    }
+    else
+    {
+      /* Subset subrs: collect used subroutines, leaving all unused ones behind */
+      if (!subr_subsetter.subset (acc, plan->glyphs, plan->drop_hints))
+        return false;
+
+      /* encode charstrings, global subrs, local subrs with new subroutine numbers */
+      if (!subr_subsetter.encode_charstrings (acc, plan->glyphs, subset_charstrings))
+        return false;
+
+      if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
+        return false;
+
+      /* global subrs */
+      unsigned int dataSize = subset_globalsubrs.total_size ();
+      offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
+      if (unlikely (offsets.globalSubrsInfo.offSize > 4))
+        return false;
+      offsets.globalSubrsInfo.size = CFF1Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
+
+      /* local subrs */
+      if (!offsets.localSubrsInfos.resize (orig_fdcount))
+        return false;
+      if (!subset_localsubrs.resize (orig_fdcount))
+        return false;
+      for (unsigned int fd = 0; fd < orig_fdcount; fd++)
+      {
+        subset_localsubrs[fd].init ();
+        offsets.localSubrsInfos[fd].init ();
+        if (fdmap.includes (fd))
+        {
+          if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
+            return false;
+
+          unsigned int dataSize = subset_localsubrs[fd].total_size ();
+          if (dataSize > 0)
+          {
+            offsets.localSubrsInfos[fd].offset = final_size;
+            offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
+            if (unlikely (offsets.localSubrsInfos[fd].offSize > 4))
+              return false;
+            offsets.localSubrsInfos[fd].size = CFF1Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
+          }
+        }
+      }
+    }
+
+    /* global subrs */
+    offsets.globalSubrsInfo.offset = final_size;
+    final_size += offsets.globalSubrsInfo.size;
+
+    /* Encoding */
+    if (!subset_encoding)
+      offsets.encodingOffset = acc.topDict.EncodingOffset;
+    else
+    {
+      offsets.encodingOffset = final_size;
+      final_size += plan_subset_encoding (acc, plan);
+    }
+
+    /* Charset */
+    if (!subset_charset && acc.is_predef_charset ())
+      offsets.charsetInfo.offset = acc.topDict.CharsetOffset;
+    else
+      offsets.charsetInfo.offset = final_size;
+    final_size += offsets.charsetInfo.size;
+
+    /* FDSelect */
+    if (acc.fdSelect != &Null(CFF1FDSelect))
+    {
+      offsets.FDSelectInfo.offset = final_size;
+      final_size += offsets.FDSelectInfo.size;
+    }
+
+    /* FDArray (FDIndex) */
+    if (acc.fdArray != &Null(CFF1FDArray)) {
+      offsets.FDArrayInfo.offset = final_size;
+      cff1_font_dict_op_serializer_t fontSzr;
+      unsigned int dictsSize = 0;
+      for (unsigned int i = 0; i < acc.fontDicts.length; i++)
+        if (fdmap.includes (i))
+          dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
+
+      offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
+      if (unlikely (offsets.FDArrayInfo.offSize > 4))
+        return false;
+      final_size += CFF1Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
+    }
+
+    /* CharStrings */
+    {
+      offsets.charStringsInfo.offset = final_size;
+      unsigned int dataSize = subset_charstrings.total_size ();
+      offsets.charStringsInfo.offSize = calcOffSize (dataSize);
+      if (unlikely (offsets.charStringsInfo.offSize > 4))
+        return false;
+      final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs.length, dataSize);
+    }
+
+    /* private dicts & local subrs */
+    offsets.privateDictInfo.offset = final_size;
+    for (unsigned int i = 0; i < orig_fdcount; i++)
+    {
+      if (fdmap.includes (i))
+      {
+        bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
+        cff_private_dict_op_serializer_t privSzr (desubroutinize, plan->drop_hints);
+        unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
+        table_info_t  privInfo = { final_size, priv_size, 0 };
+        font_dict_values_mod_t fontdict_mod;
+        if (!acc.is_CID ())
+          fontdict_mod.init ( &Null(cff1_font_dict_values_t), CFF_UNDEF_SID, privInfo );
+        else
+          fontdict_mod.init ( &acc.fontDicts[i], sidmap[acc.fontDicts[i].fontName], privInfo );
+        fontdicts_mod.push (fontdict_mod);
+        final_size += privInfo.size;
+
+        if (!plan->desubroutinize && has_localsubrs)
+        {
+          offsets.localSubrsInfos[i].offset = final_size;
+          final_size += offsets.localSubrsInfos[i].size;
+        }
+      }
+    }
+
+    if (!acc.is_CID ())
+      offsets.privateDictInfo = fontdicts_mod[0].privateDictInfo;
+
+    return ((subset_charstrings.length == plan->glyphs.length)
+           && (fontdicts_mod.length == subset_fdcount));
+  }
+
+  unsigned int get_final_size () const  { return final_size; }
+
+  unsigned int        final_size;
+  hb_vector_t<unsigned int>     topdict_sizes;
+  cff1_top_dict_values_mod_t    topdict_mod;
+  cff1_sub_table_offsets_t      offsets;
+
+  unsigned int    num_glyphs;
+  unsigned int    orig_fdcount;
+  unsigned int    subset_fdcount;
+  unsigned int    subset_fdselect_format;
+  hb_vector_t<code_pair_t>   subset_fdselect_ranges;
+
+  /* font dict index remap table from fullset FDArray to subset FDArray.
+   * set to CFF_UNDEF_CODE if excluded from subset */
+  remap_t   fdmap;
+
+  str_buff_vec_t                subset_charstrings;
+  str_buff_vec_t                subset_globalsubrs;
+  hb_vector_t<str_buff_vec_t>   subset_localsubrs;
+  hb_vector_t<font_dict_values_mod_t>  fontdicts_mod;
+
+  bool          drop_hints;
+
+  bool          gid_renum;
+  bool          subset_encoding;
+  uint8_t       subset_enc_format;
+  unsigned int  subset_enc_num_codes;
+  range_list_t  subset_enc_code_ranges;
+  hb_vector_t<code_pair_t>  subset_enc_supp_codes;
+
+  uint8_t       subset_charset_format;
+  range_list_t  subset_charset_ranges;
+  bool          subset_charset;
+
+  remap_sid_t   sidmap;
+  unsigned int  topDictModSIDs[name_dict_values_t::ValCount];
+
+  bool          desubroutinize;
+  cff1_subr_subsetter_t       subr_subsetter;
+};
+
+static inline bool _write_cff1 (const cff_subset_plan &plan,
+                                const OT::cff1::accelerator_subset_t  &acc,
+                                const hb_vector_t<hb_codepoint_t>& glyphs,
+                                unsigned int dest_sz,
+                                void *dest)
+{
+  hb_serialize_context_t c (dest, dest_sz);
+
+  OT::cff1 *cff = c.start_serialize<OT::cff1> ();
+  if (unlikely (!c.extend_min (*cff)))
+    return false;
+
+  /* header */
+  cff->version.major.set (0x01);
+  cff->version.minor.set (0x00);
+  cff->nameIndex.set (cff->min_size);
+  cff->offSize.set (4); /* unused? */
+
+  /* name INDEX */
+  {
+    assert (cff->nameIndex == (unsigned) (c.head - c.start));
+    CFF1NameIndex *dest = c.start_embed<CFF1NameIndex> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, *acc.nameIndex)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF name INDEX");
+      return false;
+    }
+  }
+
+  /* top dict INDEX */
+  {
+    assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start));
+    CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict> > ();
+    if (dest == nullptr) return false;
+    cff1_top_dict_op_serializer_t topSzr;
+    top_dict_modifiers_t  modifier (plan.offsets, plan.topDictModSIDs);
+    if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize,
+                                    &plan.topdict_mod, 1,
+                                    plan.topdict_sizes, topSzr, modifier)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
+      return false;
+    }
+  }
+
+  /* String INDEX */
+  {
+    assert (plan.offsets.stringIndexInfo.offset == (unsigned) (c.head - c.start));
+    CFF1StringIndex *dest = c.start_embed<CFF1StringIndex> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, *acc.stringIndex, plan.offsets.stringIndexInfo.offSize, plan.sidmap)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF string INDEX");
+      return false;
+    }
+  }
+
+  /* global subrs */
+  {
+    assert (plan.offsets.globalSubrsInfo.offset != 0);
+    assert (plan.offsets.globalSubrsInfo.offset == (unsigned) (c.head - c.start));
+
+    CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
+      return false;
+    }
+  }
+
+  /* Encoding */
+  if (plan.subset_encoding)
+  {
+    assert (plan.offsets.encodingOffset == (unsigned) (c.head - c.start));
+    Encoding *dest = c.start_embed<Encoding> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c,
+                                    plan.subset_enc_format,
+                                    plan.subset_enc_num_codes,
+                                    plan.subset_enc_code_ranges,
+                                    plan.subset_enc_supp_codes)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize Encoding");
+      return false;
+    }
+  }
+
+  /* Charset */
+  if (plan.subset_charset)
+  {
+    assert (plan.offsets.charsetInfo.offset == (unsigned) (c.head - c.start));
+    Charset *dest = c.start_embed<Charset> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c,
+                                    plan.subset_charset_format,
+                                    plan.num_glyphs,
+                                    plan.subset_charset_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize Charset");
+      return false;
+    }
+  }
+
+  /* FDSelect */
+  if (acc.fdSelect != &Null(CFF1FDSelect))
+  {
+    assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
+
+    if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs.length, *acc.fdSelect, acc.fdCount,
+                                              plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
+                                              plan.subset_fdselect_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF subset FDSelect");
+      return false;
+    }
+  }
+
+  /* FDArray (FD Index) */
+  if (acc.fdArray != &Null(CFF1FDArray))
+  {
+    assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
+    CFF1FDArray  *fda = c.start_embed<CFF1FDArray> ();
+    if (unlikely (fda == nullptr)) return false;
+    cff1_font_dict_op_serializer_t  fontSzr;
+    if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
+                                   plan.fontdicts_mod,
+                                   fontSzr)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF FDArray");
+      return false;
+    }
+  }
+
+  /* CharStrings */
+  {
+    assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
+    CFF1CharStrings  *cs = c.start_embed<CFF1CharStrings> ();
+    if (unlikely (cs == nullptr)) return false;
+    if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF CharStrings");
+      return false;
+    }
+  }
+
+  /* private dicts & local subrs */
+  assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start));
+  for (unsigned int i = 0; i < acc.privateDicts.length; i++)
+  {
+    if (plan.fdmap.includes (i))
+    {
+      PrivateDict  *pd = c.start_embed<PrivateDict> ();
+      if (unlikely (pd == nullptr)) return false;
+      unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
+      bool result;
+      cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+      /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
+      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
+      result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
+      if (unlikely (!result))
+      {
+        DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
+        return false;
+      }
+      if (plan.offsets.localSubrsInfos[i].size > 0)
+      {
+        CFF1Subrs *dest = c.start_embed <CFF1Subrs> ();
+        if (unlikely (dest == nullptr)) return false;
+        if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
+        {
+          DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
+          return false;
+        }
+      }
+    }
+  }
+
+  assert (c.head == c.end);
+  c.end_serialize ();
+
+  return true;
+}
+
+static bool
+_hb_subset_cff1 (const OT::cff1::accelerator_subset_t  &acc,
+                const char              *data,
+                hb_subset_plan_t        *plan,
+                hb_blob_t               **prime /* OUT */)
+{
+  cff_subset_plan cff_plan;
+
+  if (unlikely (!cff_plan.create (acc, plan)))
+  {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
+    return false;
+  }
+
+  unsigned int  cff_prime_size = cff_plan.get_final_size ();
+  char *cff_prime_data = (char *) calloc (1, cff_prime_size);
+
+  if (unlikely (!_write_cff1 (cff_plan, acc, plan->glyphs,
+                              cff_prime_size, cff_prime_data))) {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff.");
+    free (cff_prime_data);
+    return false;
+  }
+
+  *prime = hb_blob_create (cff_prime_data,
+                           cff_prime_size,
+                           HB_MEMORY_MODE_READONLY,
+                           cff_prime_data,
+                           free);
+  return true;
+}
+
+/**
+ * hb_subset_cff1:
+ * Subsets the CFF table according to a provided plan.
+ *
+ * Return value: subsetted cff table.
+ **/
+bool
+hb_subset_cff1 (hb_subset_plan_t *plan,
+                hb_blob_t       **prime /* OUT */)
+{
+  hb_blob_t *cff_blob = hb_sanitize_context_t().reference_table<CFF::cff1> (plan->source);
+  const char *data = hb_blob_get_data(cff_blob, nullptr);
+
+  OT::cff1::accelerator_subset_t acc;
+  acc.init(plan->source);
+  bool result = likely (acc.is_valid ()) &&
+                        _hb_subset_cff1 (acc, data, plan, prime);
+  hb_blob_destroy (cff_blob);
+  acc.fini ();
+
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff1.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_SUBSET_CFF1_HH
+#define HB_SUBSET_CFF1_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+
+HB_INTERNAL bool
+hb_subset_cff1 (hb_subset_plan_t *plan,
+               hb_blob_t        **cff_prime /* OUT */);
+
+#endif /* HB_SUBSET_CFF1_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff2.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,624 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-set.h"
+#include "hb-subset-cff2.hh"
+#include "hb-subset-plan.hh"
+#include "hb-subset-cff-common.hh"
+#include "hb-cff2-interp-cs.hh"
+
+using namespace CFF;
+
+struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t
+{
+  cff2_sub_table_offsets_t ()
+    : cff_sub_table_offsets_t (),
+      varStoreOffset (0)
+  {}
+
+  unsigned int  varStoreOffset;
+};
+
+struct cff2_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<>
+{
+  bool serialize (hb_serialize_context_t *c,
+                  const op_str_t &opstr,
+                  const cff2_sub_table_offsets_t &offsets) const
+  {
+    TRACE_SERIALIZE (this);
+
+    switch (opstr.op)
+    {
+      case OpCode_vstore:
+        return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.varStoreOffset));
+
+      default:
+        return_trace (cff_top_dict_op_serializer_t<>::serialize (c, opstr, offsets));
+    }
+  }
+
+  unsigned int calculate_serialized_size (const op_str_t &opstr) const
+  {
+    switch (opstr.op)
+    {
+      case OpCode_vstore:
+        return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
+
+      default:
+        return cff_top_dict_op_serializer_t<>::calculate_serialized_size (opstr);
+    }
+  }
+};
+
+struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t>
+{
+  static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    switch (op)
+    {
+      case OpCode_return:
+      case OpCode_endchar:
+        /* dummy opcodes in CFF2. ignore */
+        break;
+
+      case OpCode_hstem:
+      case OpCode_hstemhm:
+      case OpCode_vstem:
+      case OpCode_vstemhm:
+      case OpCode_hintmask:
+      case OpCode_cntrmask:
+        if (param.drop_hints)
+        {
+          env.clear_args ();
+          return;
+        }
+        HB_FALLTHROUGH;
+
+      default:
+        SUPER::flush_args_and_op (op, env, param);
+        break;
+    }
+  }
+
+  static void flush_args (cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    for (unsigned int i = 0; i < env.argStack.get_count ();)
+    {
+      const blend_arg_t &arg = env.argStack[i];
+      if (arg.blending ())
+      {
+        if (unlikely (!((arg.numValues > 0) && (env.argStack.get_count () >= arg.numValues))))
+        {
+          env.set_error ();
+          return;
+        }
+        flatten_blends (arg, i, env, param);
+        i += arg.numValues;
+      }
+      else
+      {
+        str_encoder_t  encoder (param.flatStr);
+        encoder.encode_num (arg);
+        i++;
+      }
+    }
+    SUPER::flush_args (env, param);
+  }
+
+  static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    /* flatten the default values */
+    str_encoder_t  encoder (param.flatStr);
+    for (unsigned int j = 0; j < arg.numValues; j++)
+    {
+      const blend_arg_t &arg1 = env.argStack[i + j];
+      if (unlikely (!((arg1.blending () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) &&
+              (arg1.deltas.length == env.get_region_count ())))))
+      {
+        env.set_error ();
+        return;
+      }
+      encoder.encode_num (arg1);
+    }
+    /* flatten deltas for each value */
+    for (unsigned int j = 0; j < arg.numValues; j++)
+    {
+      const blend_arg_t &arg1 = env.argStack[i + j];
+      for (unsigned int k = 0; k < arg1.deltas.length; k++)
+        encoder.encode_num (arg1.deltas[k]);
+    }
+    /* flatten the number of values followed by blend operator */
+    encoder.encode_int (arg.numValues);
+    encoder.encode_op (OpCode_blendcs);
+  }
+
+  static void flush_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+  {
+    switch (op)
+    {
+      case OpCode_return:
+      case OpCode_endchar:
+        return;
+      default:
+        str_encoder_t  encoder (param.flatStr);
+        encoder.encode_op (op);
+    }
+  }
+
+  private:
+  typedef cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t> SUPER;
+  typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t, flatten_param_t> CSOPSET;
+};
+
+struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t>
+{
+  static void process_op (op_code_t op, cff2_cs_interp_env_t &env, subr_subset_param_t& param)
+  {
+    switch (op) {
+
+      case OpCode_return:
+        param.current_parsed_str->set_parsed ();
+        env.returnFromSubr ();
+        param.set_current_str (env, false);
+        break;
+
+      case OpCode_endchar:
+        param.current_parsed_str->set_parsed ();
+        SUPER::process_op (op, env, param);
+        break;
+
+      case OpCode_callsubr:
+        process_call_subr (op, CSType_LocalSubr, env, param, env.localSubrs, param.local_closure);
+        break;
+
+      case OpCode_callgsubr:
+        process_call_subr (op, CSType_GlobalSubr, env, param, env.globalSubrs, param.global_closure);
+        break;
+
+      default:
+        SUPER::process_op (op, env, param);
+        param.current_parsed_str->add_op (op, env.str_ref);
+        break;
+    }
+  }
+
+  protected:
+  static void process_call_subr (op_code_t op, cs_type_t type,
+                                 cff2_cs_interp_env_t &env, subr_subset_param_t& param,
+                                 cff2_biased_subrs_t& subrs, hb_set_t *closure)
+  {
+    byte_str_ref_t    str_ref = env.str_ref;
+    env.callSubr (subrs, type);
+    param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
+    hb_set_add (closure, env.context.subr_num);
+    param.set_current_str (env, true);
+  }
+
+  private:
+  typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+};
+
+struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_subr_subset_t>
+{
+  static void finalize_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+  {
+    /* vsindex is inserted at the beginning of the charstring as necessary */
+    if (env.seen_vsindex ())
+    {
+      number_t  ivs;
+      ivs.set_int ((int)env.get_ivs ());
+      charstring.set_prefix (ivs, OpCode_vsindexcs);
+    }
+  }
+};
+
+struct cff2_subset_plan {
+  cff2_subset_plan ()
+    : final_size (0),
+      orig_fdcount (0),
+      subset_fdcount(1),
+      subset_fdselect_format (0),
+      drop_hints (false),
+      desubroutinize (false)
+  {
+    subset_fdselect_ranges.init ();
+    fdmap.init ();
+    subset_charstrings.init ();
+    subset_globalsubrs.init ();
+    subset_localsubrs.init ();
+    privateDictInfos.init ();
+  }
+
+  ~cff2_subset_plan ()
+  {
+    subset_fdselect_ranges.fini ();
+    fdmap.fini ();
+    subset_charstrings.fini_deep ();
+    subset_globalsubrs.fini_deep ();
+    subset_localsubrs.fini_deep ();
+    privateDictInfos.fini ();
+  }
+
+  bool create (const OT::cff2::accelerator_subset_t &acc,
+              hb_subset_plan_t *plan)
+  {
+    final_size = 0;
+    orig_fdcount = acc.fdArray->count;
+
+    drop_hints = plan->drop_hints;
+    desubroutinize = plan->desubroutinize;
+
+    /* CFF2 header */
+    final_size += OT::cff2::static_size;
+
+    /* top dict */
+    {
+      cff2_top_dict_op_serializer_t topSzr;
+      offsets.topDictInfo.size = TopDict::calculate_serialized_size (acc.topDict, topSzr);
+      final_size += offsets.topDictInfo.size;
+    }
+
+    if (desubroutinize)
+    {
+      /* Flatten global & local subrs */
+      subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_flatten_t>
+                    flattener(acc, plan->glyphs, plan->drop_hints);
+      if (!flattener.flatten (subset_charstrings))
+        return false;
+
+      /* no global/local subroutines */
+      offsets.globalSubrsInfo.size = CFF2Subrs::calculate_serialized_size (1, 0, 0);
+    }
+    else
+    {
+      /* Subset subrs: collect used subroutines, leaving all unused ones behind */
+      if (!subr_subsetter.subset (acc, plan->glyphs, plan->drop_hints))
+        return false;
+
+      /* encode charstrings, global subrs, local subrs with new subroutine numbers */
+      if (!subr_subsetter.encode_charstrings (acc, plan->glyphs, subset_charstrings))
+        return false;
+
+      if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs))
+        return false;
+
+      /* global subrs */
+      unsigned int dataSize = subset_globalsubrs.total_size ();
+      offsets.globalSubrsInfo.offSize = calcOffSize (dataSize);
+      offsets.globalSubrsInfo.size = CFF2Subrs::calculate_serialized_size (offsets.globalSubrsInfo.offSize, subset_globalsubrs.length, dataSize);
+
+      /* local subrs */
+      if (!offsets.localSubrsInfos.resize (orig_fdcount))
+        return false;
+      if (!subset_localsubrs.resize (orig_fdcount))
+        return false;
+      for (unsigned int fd = 0; fd < orig_fdcount; fd++)
+      {
+        subset_localsubrs[fd].init ();
+        offsets.localSubrsInfos[fd].init ();
+        if (fdmap.includes (fd))
+        {
+          if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
+            return false;
+
+          unsigned int dataSize = subset_localsubrs[fd].total_size ();
+          if (dataSize > 0)
+          {
+            offsets.localSubrsInfos[fd].offset = final_size;
+            offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
+            offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
+          }
+        }
+      }
+    }
+
+    /* global subrs */
+    offsets.globalSubrsInfo.offset = final_size;
+    final_size += offsets.globalSubrsInfo.size;
+
+    /* variation store */
+    if (acc.varStore != &Null(CFF2VariationStore))
+    {
+      offsets.varStoreOffset = final_size;
+      final_size += acc.varStore->get_size ();
+    }
+
+    /* FDSelect */
+    if (acc.fdSelect != &Null(CFF2FDSelect))
+    {
+      offsets.FDSelectInfo.offset = final_size;
+      if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
+                                  orig_fdcount,
+                                  *(const FDSelect *)acc.fdSelect,
+                                  subset_fdcount,
+                                  offsets.FDSelectInfo.size,
+                                  subset_fdselect_format,
+                                  subset_fdselect_ranges,
+                                  fdmap)))
+        return false;
+
+      final_size += offsets.FDSelectInfo.size;
+    }
+    else
+      fdmap.identity (1);
+
+    /* FDArray (FDIndex) */
+    {
+      offsets.FDArrayInfo.offset = final_size;
+      cff_font_dict_op_serializer_t fontSzr;
+      unsigned int dictsSize = 0;
+      for (unsigned int i = 0; i < acc.fontDicts.length; i++)
+        if (fdmap.includes (i))
+          dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
+
+      offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
+      final_size += CFF2Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
+    }
+
+    /* CharStrings */
+    {
+      offsets.charStringsInfo.offset = final_size;
+      unsigned int dataSize = subset_charstrings.total_size ();
+      offsets.charStringsInfo.offSize = calcOffSize (dataSize);
+      final_size += CFF2CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs.length, dataSize);
+    }
+
+    /* private dicts & local subrs */
+    offsets.privateDictsOffset = final_size;
+    for (unsigned int i = 0; i < orig_fdcount; i++)
+    {
+      if (fdmap.includes (i))
+      {
+        bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
+        cff_private_dict_op_serializer_t privSzr (desubroutinize, drop_hints);
+        unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
+        table_info_t  privInfo = { final_size, priv_size, 0 };
+        privateDictInfos.push (privInfo);
+        final_size += privInfo.size;
+
+        if (!plan->desubroutinize && has_localsubrs)
+        {
+          offsets.localSubrsInfos[i].offset = final_size;
+          final_size += offsets.localSubrsInfos[i].size;
+        }
+      }
+    }
+
+    return true;
+  }
+
+  unsigned int get_final_size () const  { return final_size; }
+
+  unsigned int  final_size;
+  cff2_sub_table_offsets_t offsets;
+
+  unsigned int    orig_fdcount;
+  unsigned int    subset_fdcount;
+  unsigned int    subset_fdselect_format;
+  hb_vector_t<code_pair_t>   subset_fdselect_ranges;
+
+  remap_t   fdmap;
+
+  str_buff_vec_t            subset_charstrings;
+  str_buff_vec_t            subset_globalsubrs;
+  hb_vector_t<str_buff_vec_t> subset_localsubrs;
+  hb_vector_t<table_info_t>  privateDictInfos;
+
+  bool      drop_hints;
+  bool      desubroutinize;
+  cff2_subr_subsetter_t       subr_subsetter;
+};
+
+static inline bool _write_cff2 (const cff2_subset_plan &plan,
+                                const OT::cff2::accelerator_subset_t  &acc,
+                                const hb_vector_t<hb_codepoint_t>& glyphs,
+                                unsigned int dest_sz,
+                                void *dest)
+{
+  hb_serialize_context_t c (dest, dest_sz);
+
+  OT::cff2 *cff2 = c.start_serialize<OT::cff2> ();
+  if (unlikely (!c.extend_min (*cff2)))
+    return false;
+
+  /* header */
+  cff2->version.major.set (0x02);
+  cff2->version.minor.set (0x00);
+  cff2->topDict.set (OT::cff2::static_size);
+
+  /* top dict */
+  {
+    assert (cff2->topDict == (unsigned) (c.head - c.start));
+    cff2->topDictSize.set (plan.offsets.topDictInfo.size);
+    TopDict &dict = cff2 + cff2->topDict;
+    cff2_top_dict_op_serializer_t topSzr;
+    if (unlikely (!dict.serialize (&c, acc.topDict, topSzr, plan.offsets)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 top dict");
+      return false;
+    }
+  }
+
+  /* global subrs */
+  {
+    assert (cff2->topDict + plan.offsets.topDictInfo.size == (unsigned) (c.head - c.start));
+    CFF2Subrs *dest = c.start_embed <CFF2Subrs> ();
+    if (unlikely (dest == nullptr)) return false;
+    if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
+      return false;
+    }
+  }
+
+  /* variation store */
+  if (acc.varStore != &Null(CFF2VariationStore))
+  {
+    assert (plan.offsets.varStoreOffset == (unsigned) (c.head - c.start));
+    CFF2VariationStore *dest = c.start_embed<CFF2VariationStore> ();
+    if (unlikely (!dest->serialize (&c, acc.varStore)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Variation Store");
+      return false;
+    }
+  }
+
+  /* FDSelect */
+  if (acc.fdSelect != &Null(CFF2FDSelect))
+  {
+    assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start));
+
+    if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs.length, *(const FDSelect *)acc.fdSelect, acc.fdArray->count,
+                                              plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
+                                              plan.subset_fdselect_ranges)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 subset FDSelect");
+      return false;
+    }
+  }
+
+  /* FDArray (FD Index) */
+  {
+    assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start));
+    CFF2FDArray  *fda = c.start_embed<CFF2FDArray> ();
+    if (unlikely (fda == nullptr)) return false;
+    cff_font_dict_op_serializer_t  fontSzr;
+    if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
+                                   acc.fontDicts, plan.subset_fdcount, plan.fdmap,
+                                   fontSzr, plan.privateDictInfos)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 FDArray");
+      return false;
+    }
+  }
+
+  /* CharStrings */
+  {
+    assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start));
+    CFF2CharStrings  *cs = c.start_embed<CFF2CharStrings> ();
+    if (unlikely (cs == nullptr)) return false;
+    if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
+    {
+      DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 CharStrings");
+      return false;
+    }
+  }
+
+  /* private dicts & local subrs */
+  assert (plan.offsets.privateDictsOffset == (unsigned) (c.head - c.start));
+  for (unsigned int i = 0; i < acc.privateDicts.length; i++)
+  {
+    if (plan.fdmap.includes (i))
+    {
+      PrivateDict  *pd = c.start_embed<PrivateDict> ();
+      if (unlikely (pd == nullptr)) return false;
+      unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size;
+      bool result;
+      cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
+      /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
+      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
+      result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
+      if (unlikely (!result))
+      {
+        DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
+        return false;
+      }
+      if (plan.offsets.localSubrsInfos[i].size > 0)
+      {
+        CFF2Subrs *dest = c.start_embed <CFF2Subrs> ();
+        if (unlikely (dest == nullptr)) return false;
+        if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
+        {
+          DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
+          return false;
+        }
+      }
+    }
+  }
+
+  assert (c.head == c.end);
+  c.end_serialize ();
+
+  return true;
+}
+
+static bool
+_hb_subset_cff2 (const OT::cff2::accelerator_subset_t  &acc,
+                const char                    *data,
+                hb_subset_plan_t                *plan,
+                hb_blob_t                      **prime /* OUT */)
+{
+  cff2_subset_plan cff2_plan;
+
+  if (unlikely (!cff2_plan.create (acc, plan)))
+  {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff2 subsetting plan.");
+    return false;
+  }
+
+  unsigned int  cff2_prime_size = cff2_plan.get_final_size ();
+  char *cff2_prime_data = (char *) calloc (1, cff2_prime_size);
+
+  if (unlikely (!_write_cff2 (cff2_plan, acc, plan->glyphs,
+                              cff2_prime_size, cff2_prime_data))) {
+    DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff2.");
+    free (cff2_prime_data);
+    return false;
+  }
+
+  *prime = hb_blob_create (cff2_prime_data,
+                                cff2_prime_size,
+                                HB_MEMORY_MODE_READONLY,
+                                cff2_prime_data,
+                                free);
+  return true;
+}
+
+/**
+ * hb_subset_cff2:
+ * Subsets the CFF2 table according to a provided plan.
+ *
+ * Return value: subsetted cff2 table.
+ **/
+bool
+hb_subset_cff2 (hb_subset_plan_t *plan,
+                hb_blob_t       **prime /* OUT */)
+{
+  hb_blob_t *cff2_blob = hb_sanitize_context_t().reference_table<CFF::cff2> (plan->source);
+  const char *data = hb_blob_get_data(cff2_blob, nullptr);
+
+  OT::cff2::accelerator_subset_t acc;
+  acc.init(plan->source);
+  bool result = likely (acc.is_valid ()) &&
+                _hb_subset_cff2 (acc, data, plan, prime);
+
+  hb_blob_destroy (cff2_blob);
+  acc.fini ();
+
+  return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-cff2.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018 Adobe Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Adobe Author(s): Michiharu Ariza
+ */
+
+#ifndef HB_SUBSET_CFF2_HH
+#define HB_SUBSET_CFF2_HH
+
+#include "hb.hh"
+
+#include "hb-subset-plan.hh"
+
+HB_INTERNAL bool
+hb_subset_cff2 (hb_subset_plan_t *plan,
+               hb_blob_t       **cff2_prime /* OUT */);
+
+#endif /* HB_SUBSET_CFF2_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,310 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Roderick Sheeter
+ */
+
+#include "hb-open-type.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-set.h"
+#include "hb-subset-glyf.hh"
+
+static bool
+_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
+                                     hb_vector_t<hb_codepoint_t> &glyph_ids,
+                                     hb_bool_t drop_hints,
+                                     bool *use_short_loca /* OUT */,
+                                     unsigned int *glyf_size /* OUT */,
+                                     unsigned int *loca_size /* OUT */,
+                                     hb_vector_t<unsigned int> *instruction_ranges /* OUT */)
+{
+  unsigned int total = 0;
+  for (unsigned int i = 0; i < glyph_ids.length; i++)
+  {
+    hb_codepoint_t next_glyph = glyph_ids[i];
+    if (!instruction_ranges->resize (instruction_ranges->length + 2))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
+      return false;
+    }
+    unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2];
+    *instruction_start = 0;
+    unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1];
+    *instruction_end = 0;
+
+    unsigned int start_offset, end_offset;
+    if (unlikely (!(glyf.get_offsets (next_glyph, &start_offset, &end_offset) &&
+                    glyf.remove_padding (start_offset, &end_offset))))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
+      continue;
+    }
+    if (end_offset - start_offset < OT::glyf::GlyphHeader::static_size)
+      continue; /* 0-length glyph */
+
+    if (drop_hints)
+    {
+      if (unlikely (!glyf.get_instruction_offsets (start_offset, end_offset,
+                                                   instruction_start, instruction_end)))
+      {
+        DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", next_glyph);
+        return false;
+      }
+    }
+
+    total += end_offset - start_offset - (*instruction_end - *instruction_start);
+    /* round2 so short loca will work */
+    total += total % 2;
+  }
+
+  *glyf_size = total;
+  *use_short_loca = (total <= 131070);
+  *loca_size = (glyph_ids.length + 1)
+      * (*use_short_loca ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));
+
+  DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
+            total,
+            *loca_size,
+            *use_short_loca ? "short" : "long");
+  return true;
+}
+
+static bool
+_write_loca_entry (unsigned int  id,
+                   unsigned int  offset,
+                   bool          is_short,
+                   void         *loca_prime,
+                   unsigned int  loca_size)
+{
+  unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
+  if ((id + 1) * entry_size <= loca_size)
+  {
+    if (is_short) {
+      ((OT::HBUINT16*) loca_prime) [id].set (offset / 2);
+    } else {
+      ((OT::HBUINT32*) loca_prime) [id].set (offset);
+    }
+    return true;
+  }
+
+  // Offset was not written because the write is out of bounds.
+  DEBUG_MSG(SUBSET,
+            nullptr,
+            "WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
+            id,
+            loca_size);
+  return false;
+}
+
+static void
+_update_components (hb_subset_plan_t * plan,
+                    char * glyph_start,
+                    unsigned int length)
+{
+  OT::glyf::CompositeGlyphHeader::Iterator iterator;
+  if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
+                                                    length,
+                                                    &iterator))
+  {
+    do
+    {
+      hb_codepoint_t new_gid;
+      if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
+                                      &new_gid))
+        continue;
+
+      ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex.set (new_gid);
+    } while (iterator.move_to_next ());
+  }
+}
+
+static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int length)
+{
+  /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
+  OT::glyf::CompositeGlyphHeader::Iterator composite_it;
+  if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (glyf_prime, length, &composite_it))) return false;
+  const OT::glyf::CompositeGlyphHeader *glyph;
+  do {
+    glyph = composite_it.current;
+    OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&glyph->flags);
+    flags->set ( (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS);
+  } while (composite_it.move_to_next ());
+  return true;
+}
+
+static bool
+_write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
+                            const OT::glyf::accelerator_t &glyf,
+                            const char                    *glyf_data,
+                            bool                           use_short_loca,
+                            hb_vector_t<unsigned int> &instruction_ranges,
+                            unsigned int                   glyf_prime_size,
+                            char                          *glyf_prime_data /* OUT */,
+                            unsigned int                   loca_prime_size,
+                            char                          *loca_prime_data /* OUT */)
+{
+  hb_vector_t<hb_codepoint_t> &glyph_ids = plan->glyphs;
+  char *glyf_prime_data_next = glyf_prime_data;
+
+  bool success = true;
+  for (unsigned int i = 0; i < glyph_ids.length; i++)
+  {
+    unsigned int start_offset, end_offset;
+    if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset) &&
+                    glyf.remove_padding (start_offset, &end_offset))))
+      end_offset = start_offset = 0;
+
+    unsigned int instruction_start = instruction_ranges[i * 2];
+    unsigned int instruction_end = instruction_ranges[i * 2 + 1];
+
+    int length = end_offset - start_offset - (instruction_end - instruction_start);
+
+    if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
+    {
+      DEBUG_MSG(SUBSET,
+                 nullptr,
+                 "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
+                 i, length);
+      return false;
+    }
+
+    if (instruction_start == instruction_end)
+      memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
+    else
+    {
+      memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset);
+      memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end);
+      /* if the instructions end at the end this was a composite glyph, else simple */
+      if (instruction_end == end_offset)
+      {
+        if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false;
+      }
+      else
+        /* zero instruction length, which is just before instruction_start */
+        memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
+    }
+
+    success = success && _write_loca_entry (i,
+                                            glyf_prime_data_next - glyf_prime_data,
+                                            use_short_loca,
+                                            loca_prime_data,
+                                            loca_prime_size);
+    _update_components (plan, glyf_prime_data_next, length);
+
+    // TODO: don't align to two bytes if using long loca.
+    glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca.
+  }
+
+  success = success && _write_loca_entry (glyph_ids.length,
+                                          glyf_prime_data_next - glyf_prime_data,
+                                          use_short_loca,
+                                          loca_prime_data,
+                                          loca_prime_size);
+  return success;
+}
+
+static bool
+_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
+                          const char                     *glyf_data,
+                          hb_subset_plan_t               *plan,
+                          bool                           *use_short_loca,
+                          hb_blob_t                     **glyf_prime /* OUT */,
+                          hb_blob_t                     **loca_prime /* OUT */)
+{
+  // TODO(grieger): Sanity check allocation size for the new table.
+  hb_vector_t<hb_codepoint_t> &glyphs_to_retain = plan->glyphs;
+
+  unsigned int glyf_prime_size;
+  unsigned int loca_prime_size;
+  hb_vector_t<unsigned int> instruction_ranges;
+  instruction_ranges.init ();
+
+  if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
+                                                      glyphs_to_retain,
+                                                      plan->drop_hints,
+                                                      use_short_loca,
+                                                      &glyf_prime_size,
+                                                      &loca_prime_size,
+                                                      &instruction_ranges))) {
+    instruction_ranges.fini ();
+    return false;
+  }
+
+  char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
+  char *loca_prime_data = (char *) calloc (1, loca_prime_size);
+  if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
+                                             *use_short_loca,
+                                             instruction_ranges,
+                                             glyf_prime_size, glyf_prime_data,
+                                             loca_prime_size, loca_prime_data))) {
+    free (glyf_prime_data);
+    free (loca_prime_data);
+    instruction_ranges.fini ();
+    return false;
+  }
+  instruction_ranges.fini ();
+
+  *glyf_prime = hb_blob_create (glyf_prime_data,
+                                glyf_prime_size,
+                                HB_MEMORY_MODE_READONLY,
+                                glyf_prime_data,
+                                free);
+  *loca_prime = hb_blob_create (loca_prime_data,
+                                loca_prime_size,
+                                HB_MEMORY_MODE_READONLY,
+                                loca_prime_data,
+                                free);
+  return true;
+}
+
+/**
+ * hb_subset_glyf:
+ * Subsets the glyph table according to a provided plan.
+ *
+ * Return value: subsetted glyf table.
+ *
+ * Since: 1.7.5
+ **/
+bool
+hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
+                         bool             *use_short_loca, /* OUT */
+                         hb_blob_t       **glyf_prime, /* OUT */
+                         hb_blob_t       **loca_prime /* OUT */)
+{
+  hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table<OT::glyf> (plan->source);
+  const char *glyf_data = hb_blob_get_data (glyf_blob, nullptr);
+
+  OT::glyf::accelerator_t glyf;
+  glyf.init (plan->source);
+  bool result = _hb_subset_glyf_and_loca (glyf,
+                                          glyf_data,
+                                          plan,
+                                          use_short_loca,
+                                          glyf_prime,
+                                          loca_prime);
+
+  hb_blob_destroy (glyf_blob);
+  glyf.fini ();
+
+  return result;
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-glyf.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,14 +27,14 @@
 #ifndef HB_SUBSET_GLYF_HH
 #define HB_SUBSET_GLYF_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-subset-plan.hh"
+#include "hb-subset.hh"
 
 HB_INTERNAL bool
 hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
                          bool             *use_short_loca, /* OUT */
-                         hb_blob_t       **glyf_prime /* OUT */,
-                         hb_blob_t       **loca_prime /* OUT */);
+                         hb_blob_t       **glyf_prime      /* OUT */,
+                         hb_blob_t       **loca_prime      /* OUT */);
 
 #endif /* HB_SUBSET_GLYF_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-input.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,146 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
+ */
+
+#include "hb-subset.hh"
+#include "hb-set.hh"
+
+/**
+ * hb_subset_input_create_or_fail:
+ *
+ * Return value: New subset input.
+ *
+ * Since: 1.8.0
+ **/
+hb_subset_input_t *
+hb_subset_input_create_or_fail ()
+{
+  hb_subset_input_t *input = hb_object_create<hb_subset_input_t>();
+
+  if (unlikely (!input))
+    return nullptr;
+
+  input->unicodes = hb_set_create ();
+  input->glyphs = hb_set_create ();
+  input->drop_layout = true;
+
+  return input;
+}
+
+/**
+ * hb_subset_input_reference: (skip)
+ * @subset_input: a subset_input.
+ *
+ *
+ *
+ * Return value:
+ *
+ * Since: 1.8.0
+ **/
+hb_subset_input_t *
+hb_subset_input_reference (hb_subset_input_t *subset_input)
+{
+  return hb_object_reference (subset_input);
+}
+
+/**
+ * hb_subset_input_destroy:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+void
+hb_subset_input_destroy (hb_subset_input_t *subset_input)
+{
+  if (!hb_object_destroy (subset_input)) return;
+
+  hb_set_destroy (subset_input->unicodes);
+  hb_set_destroy (subset_input->glyphs);
+
+  free (subset_input);
+}
+
+/**
+ * hb_subset_input_unicode_set:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+HB_EXTERN hb_set_t *
+hb_subset_input_unicode_set (hb_subset_input_t *subset_input)
+{
+  return subset_input->unicodes;
+}
+
+/**
+ * hb_subset_input_glyph_set:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
+HB_EXTERN hb_set_t *
+hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
+{
+  return subset_input->glyphs;
+}
+
+HB_EXTERN void
+hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
+                                hb_bool_t drop_hints)
+{
+  subset_input->drop_hints = drop_hints;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input)
+{
+  return subset_input->drop_hints;
+}
+
+HB_EXTERN void
+hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
+                                 hb_bool_t drop_layout)
+{
+  subset_input->drop_layout = drop_layout;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input)
+{
+  return subset_input->drop_layout;
+}
+
+HB_EXTERN void
+hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
+        hb_bool_t desubroutinize)
+{
+  subset_input->desubroutinize = desubroutinize;
+}
+
+HB_EXTERN hb_bool_t
+hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
+{
+  return subset_input->desubroutinize;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-input.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Roderick Sheeter
+ */
+
+#ifndef HB_SUBSET_INPUT_HH
+#define HB_SUBSET_INPUT_HH
+
+
+#include "hb.hh"
+
+#include "hb-subset.h"
+
+#include "hb-font.hh"
+
+struct hb_subset_input_t
+{
+  hb_object_header_t header;
+
+  hb_set_t *unicodes;
+  hb_set_t *glyphs;
+
+  bool drop_hints : 1;
+  bool drop_layout : 1;
+  bool desubroutinize : 1;
+  /* TODO
+   *
+   * features
+   * lookups
+   * nameIDs
+   * ...
+   */
+};
+
+
+#endif /* HB_SUBSET_INPUT_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,223 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Roderick Sheeter
+ */
+
+#include "hb-subset-plan.hh"
+#include "hb-map.hh"
+#include "hb-set.hh"
+
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-cff1-table.hh"
+
+static void
+_add_gid_and_children (const OT::glyf::accelerator_t &glyf,
+                       hb_codepoint_t gid,
+                       hb_set_t *gids_to_retain)
+{
+  if (hb_set_has (gids_to_retain, gid))
+    // Already visited this gid, ignore.
+    return;
+
+  hb_set_add (gids_to_retain, gid);
+
+  OT::glyf::CompositeGlyphHeader::Iterator composite;
+  if (glyf.get_composite (gid, &composite))
+  {
+    do
+    {
+      _add_gid_and_children (glyf, (hb_codepoint_t) composite.current->glyphIndex, gids_to_retain);
+    } while (composite.move_to_next());
+  }
+}
+
+static void
+_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
+           hb_codepoint_t gid,
+           hb_set_t *gids_to_retain)
+{
+  hb_codepoint_t base_gid, accent_gid;
+  if (cff.get_seac_components (gid, &base_gid, &accent_gid))
+  {
+    hb_set_add (gids_to_retain, base_gid);
+    hb_set_add (gids_to_retain, accent_gid);
+  }
+}
+
+static void
+_gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
+{
+  hb_set_t lookup_indices;
+  hb_ot_layout_collect_lookups (face,
+                                HB_OT_TAG_GSUB,
+                                nullptr,
+                                nullptr,
+                                nullptr,
+                                &lookup_indices);
+  hb_ot_layout_lookups_substitute_closure (face,
+                                           &lookup_indices,
+                                           gids_to_retain);
+}
+
+static void
+_remove_invalid_gids (hb_set_t *glyphs,
+                      unsigned int num_glyphs)
+{
+  hb_codepoint_t gid = HB_SET_VALUE_INVALID;
+  while (glyphs->next (&gid))
+  {
+    if (gid >= num_glyphs)
+      glyphs->del (gid);
+  }
+}
+
+static hb_set_t *
+_populate_gids_to_retain (hb_face_t *face,
+                          const hb_set_t *unicodes,
+                          bool close_over_gsub,
+                          hb_set_t *unicodes_to_retain,
+                          hb_map_t *codepoint_to_glyph,
+                          hb_vector_t<hb_codepoint_t> *glyphs)
+{
+  OT::cmap::accelerator_t cmap;
+  OT::glyf::accelerator_t glyf;
+  OT::cff1::accelerator_t cff;
+  cmap.init (face);
+  glyf.init (face);
+  cff.init (face);
+
+  hb_set_t *initial_gids_to_retain = hb_set_create ();
+  initial_gids_to_retain->add (0); // Not-def
+
+  hb_codepoint_t cp = HB_SET_VALUE_INVALID;
+  while (unicodes->next (&cp))
+  {
+    hb_codepoint_t gid;
+    if (!cmap.get_nominal_glyph (cp, &gid))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
+      continue;
+    }
+    unicodes_to_retain->add (cp);
+    codepoint_to_glyph->set (cp, gid);
+    initial_gids_to_retain->add (gid);
+  }
+
+  if (close_over_gsub)
+    // Add all glyphs needed for GSUB substitutions.
+    _gsub_closure (face, initial_gids_to_retain);
+
+  // Populate a full set of glyphs to retain by adding all referenced
+  // composite glyphs.
+  hb_codepoint_t gid = HB_SET_VALUE_INVALID;
+  hb_set_t *all_gids_to_retain = hb_set_create ();
+  while (initial_gids_to_retain->next (&gid))
+  {
+    _add_gid_and_children (glyf, gid, all_gids_to_retain);
+    if (cff.is_valid ())
+      _add_cff_seac_components (cff, gid, all_gids_to_retain);
+  }
+  hb_set_destroy (initial_gids_to_retain);
+
+  _remove_invalid_gids (all_gids_to_retain, face->get_num_glyphs ());
+
+  glyphs->alloc (all_gids_to_retain->get_population ());
+  gid = HB_SET_VALUE_INVALID;
+  while (all_gids_to_retain->next (&gid))
+    glyphs->push (gid);
+
+  cff.fini ();
+  glyf.fini ();
+  cmap.fini ();
+
+  return all_gids_to_retain;
+}
+
+static void
+_create_old_gid_to_new_gid_map (const hb_vector_t<hb_codepoint_t> &glyphs,
+                                hb_map_t *glyph_map)
+{
+  for (unsigned int i = 0; i < glyphs.length; i++) {
+    glyph_map->set (glyphs[i], i);
+  }
+}
+
+/**
+ * hb_subset_plan_create:
+ * Computes a plan for subsetting the supplied face according
+ * to a provided input. The plan describes
+ * which tables and glyphs should be retained.
+ *
+ * Return value: New subset plan.
+ *
+ * Since: 1.7.5
+ **/
+hb_subset_plan_t *
+hb_subset_plan_create (hb_face_t           *face,
+                       hb_subset_input_t   *input)
+{
+  hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
+
+  plan->drop_hints = input->drop_hints;
+  plan->drop_layout = input->drop_layout;
+  plan->desubroutinize = input->desubroutinize;
+  plan->unicodes = hb_set_create();
+  plan->glyphs.init();
+  plan->source = hb_face_reference (face);
+  plan->dest = hb_face_builder_create ();
+  plan->codepoint_to_glyph = hb_map_create();
+  plan->glyph_map = hb_map_create();
+  plan->glyphset = _populate_gids_to_retain (face,
+                                             input->unicodes,
+                                             !plan->drop_layout,
+                                             plan->unicodes,
+                                             plan->codepoint_to_glyph,
+                                             &plan->glyphs);
+  _create_old_gid_to_new_gid_map (plan->glyphs,
+                                  plan->glyph_map);
+
+  return plan;
+}
+
+/**
+ * hb_subset_plan_destroy:
+ *
+ * Since: 1.7.5
+ **/
+void
+hb_subset_plan_destroy (hb_subset_plan_t *plan)
+{
+  if (!hb_object_destroy (plan)) return;
+
+  hb_set_destroy (plan->unicodes);
+  plan->glyphs.fini ();
+  hb_face_destroy (plan->source);
+  hb_face_destroy (plan->dest);
+  hb_map_destroy (plan->codepoint_to_glyph);
+  hb_map_destroy (plan->glyph_map);
+  hb_set_destroy (plan->glyphset);
+
+  free (plan);
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.hh	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-plan.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -27,28 +27,26 @@
 #ifndef HB_SUBSET_PLAN_HH
 #define HB_SUBSET_PLAN_HH
 
-#include "hb-private.hh"
+#include "hb.hh"
 
 #include "hb-subset.h"
-#include "hb-subset-private.hh"
+#include "hb-subset-input.hh"
 
-#include "hb-object-private.hh"
-#include "hb-map-private.hh"
+#include "hb-map.hh"
 
 struct hb_subset_plan_t
 {
   hb_object_header_t header;
-  ASSERT_POD ();
 
-  hb_bool_t drop_hints;
-  hb_bool_t drop_ot_layout;
+  bool drop_hints : 1;
+  bool drop_layout : 1;
+  bool desubroutinize : 1;
 
   // For each cp that we'd like to retain maps to the corresponding gid.
   hb_set_t *unicodes;
 
-  // This list contains the complete set of glyphs to retain and may contain
-  // more glyphs then the lists above.
   hb_vector_t<hb_codepoint_t> glyphs;
+  hb_set_t *glyphset;
 
   hb_map_t *codepoint_to_glyph;
   hb_map_t *glyph_map;
@@ -57,9 +55,8 @@
   hb_face_t *source;
   hb_face_t *dest;
 
-  inline hb_bool_t
-  new_gid_for_codepoint (hb_codepoint_t codepoint,
-                         hb_codepoint_t *new_gid) const
+  bool new_gid_for_codepoint (hb_codepoint_t codepoint,
+                              hb_codepoint_t *new_gid) const
   {
     hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
     if (old_gid == HB_MAP_VALUE_INVALID)
@@ -68,9 +65,8 @@
     return new_gid_for_old_gid (old_gid, new_gid);
   }
 
-  inline hb_bool_t
-  new_gid_for_old_gid (hb_codepoint_t old_gid,
-                      hb_codepoint_t *new_gid) const
+  bool new_gid_for_old_gid (hb_codepoint_t old_gid,
+                            hb_codepoint_t *new_gid) const
   {
     hb_codepoint_t gid = glyph_map->get (old_gid);
     if (gid == HB_MAP_VALUE_INVALID)
@@ -80,7 +76,7 @@
     return true;
   }
 
-  inline hb_bool_t
+  bool
   add_table (hb_tag_t tag,
              hb_blob_t *contents)
   {
@@ -90,7 +86,7 @@
               hb_blob_get_length (contents),
               hb_blob_get_length (source_blob));
     hb_blob_destroy (source_blob);
-    return hb_subset_face_add_table(dest, tag, contents);
+    return hb_face_builder_add_table (dest, tag, contents);
   }
 };
 
@@ -98,7 +94,6 @@
 
 HB_INTERNAL hb_subset_plan_t *
 hb_subset_plan_create (hb_face_t           *face,
-                       hb_subset_profile_t *profile,
                        hb_subset_input_t   *input);
 
 HB_INTERNAL void
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2018  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Garret Rieger, Roderick Sheeter
- */
-
-#ifndef HB_SUBSET_PRIVATE_HH
-#define HB_SUBSET_PRIVATE_HH
-
-
-#include "hb-private.hh"
-
-#include "hb-subset.h"
-
-#include "hb-font-private.hh"
-
-typedef struct hb_subset_face_data_t hb_subset_face_data_t;
-
-struct hb_subset_input_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_set_t *unicodes;
-  hb_set_t *glyphs;
-
-  hb_bool_t drop_hints;
-  hb_bool_t drop_ot_layout;
-  /* TODO
-   *
-   * features
-   * lookups
-   * nameIDs
-   * ...
-   */
-};
-
-HB_INTERNAL hb_face_t *
-hb_subset_face_create (void);
-
-HB_INTERNAL hb_bool_t
-hb_subset_face_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob);
-
-#endif /* HB_SUBSET_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,293 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
+ */
+
+#include "hb.hh"
+#include "hb-open-type.hh"
+
+#include "hb-subset.hh"
+#include "hb-subset-glyf.hh"
+
+#include "hb-open-file.hh"
+#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
+#include "hb-ot-hdmx-table.hh"
+#include "hb-ot-head-table.hh"
+#include "hb-ot-hhea-table.hh"
+#include "hb-ot-hmtx-table.hh"
+#include "hb-ot-maxp-table.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-post-table.hh"
+#include "hb-ot-cff1-table.hh"
+#include "hb-ot-cff2-table.hh"
+#include "hb-ot-vorg-table.hh"
+#include "hb-ot-layout-gsub-table.hh"
+#include "hb-ot-layout-gpos-table.hh"
+
+
+static unsigned int
+_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
+                                  unsigned int table_len)
+{
+  unsigned int src_glyphs = plan->source->get_num_glyphs ();
+  unsigned int dst_glyphs = plan->glyphset->get_population ();
+
+  if (unlikely (!src_glyphs))
+    return 512 + table_len;
+
+  return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
+}
+
+template<typename TableType>
+static bool
+_subset2 (hb_subset_plan_t *plan)
+{
+  hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
+  const TableType *table = source_blob->as<TableType> ();
+
+  hb_tag_t tag = TableType::tableTag;
+  hb_bool_t result = false;
+  if (source_blob->data)
+  {
+    hb_vector_t<char> buf;
+    unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
+    if (unlikely (!buf.alloc (buf_size)))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
+      return false;
+    }
+  retry:
+    hb_serialize_context_t serializer ((void *) buf, buf_size);
+    hb_subset_context_t c (plan, &serializer);
+    result = table->subset (&c);
+    if (serializer.in_error ())
+    {
+      buf_size += (buf_size >> 1) + 32;
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
+      if (unlikely (!buf.alloc (buf_size)))
+      {
+        DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
+        return false;
+      }
+      goto retry;
+    }
+    if (result)
+    {
+      hb_blob_t *dest_blob = serializer.copy_blob ();
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
+      result = c.plan->add_table (tag, dest_blob);
+      hb_blob_destroy (dest_blob);
+    }
+    else
+    {
+      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
+      result = true;
+    }
+  }
+  else
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
+
+  hb_blob_destroy (source_blob);
+  DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
+  return result;
+}
+
+template<typename TableType>
+static bool
+_subset (hb_subset_plan_t *plan)
+{
+  hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
+  const TableType *table = source_blob->as<TableType> ();
+
+  hb_tag_t tag = TableType::tableTag;
+  hb_bool_t result = false;
+  if (source_blob->data)
+    result = table->subset (plan);
+  else
+    DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
+
+  hb_blob_destroy (source_blob);
+  DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
+  return result;
+}
+
+
+static bool
+_subset_table (hb_subset_plan_t *plan,
+               hb_tag_t          tag)
+{
+  DEBUG_MSG(SUBSET, nullptr, "begin subset %c%c%c%c", HB_UNTAG (tag));
+  bool result = true;
+  switch (tag) {
+    case HB_OT_TAG_glyf:
+      result = _subset<const OT::glyf> (plan);
+      break;
+    case HB_OT_TAG_hdmx:
+      result = _subset<const OT::hdmx> (plan);
+      break;
+    case HB_OT_TAG_head:
+      // TODO that won't work well if there is no glyf
+      DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
+      result = true;
+      break;
+    case HB_OT_TAG_hhea:
+      DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
+      return true;
+    case HB_OT_TAG_hmtx:
+      result = _subset<const OT::hmtx> (plan);
+      break;
+    case HB_OT_TAG_vhea:
+      DEBUG_MSG(SUBSET, nullptr, "skip vhea handled by vmtx");
+      return true;
+    case HB_OT_TAG_vmtx:
+      result = _subset<const OT::vmtx> (plan);
+      break;
+    case HB_OT_TAG_maxp:
+      result = _subset<const OT::maxp> (plan);
+      break;
+    case HB_OT_TAG_loca:
+      DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
+      return true;
+    case HB_OT_TAG_cmap:
+      result = _subset<const OT::cmap> (plan);
+      break;
+    case HB_OT_TAG_OS2:
+      result = _subset<const OT::OS2> (plan);
+      break;
+    case HB_OT_TAG_post:
+      result = _subset<const OT::post> (plan);
+      break;
+    case HB_OT_TAG_cff1:
+      result = _subset<const OT::cff1> (plan);
+      break;
+    case HB_OT_TAG_cff2:
+      result = _subset<const OT::cff2> (plan);
+      break;
+    case HB_OT_TAG_VORG:
+      result = _subset<const OT::VORG> (plan);
+      break;
+    case HB_OT_TAG_GDEF:
+      result = _subset2<const OT::GDEF> (plan);
+      break;
+    case HB_OT_TAG_GSUB:
+      result = _subset2<const OT::GSUB> (plan);
+      break;
+    case HB_OT_TAG_GPOS:
+      result = _subset2<const OT::GPOS> (plan);
+      break;
+
+    default:
+      hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
+      if (likely (source_table))
+        result = plan->add_table (tag, source_table);
+      else
+        result = false;
+      hb_blob_destroy (source_table);
+      break;
+  }
+  DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG (tag), result ? "ok" : "FAILED");
+  return result;
+}
+
+static bool
+_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
+{
+  switch (tag) {
+    case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */
+    case HB_TAG ('c', 'v', 't', ' '): /* hint table, fallthrough */
+    case HB_TAG ('f', 'p', 'g', 'm'): /* hint table, fallthrough */
+    case HB_TAG ('p', 'r', 'e', 'p'): /* hint table, fallthrough */
+    case HB_TAG ('h', 'd', 'm', 'x'): /* hint table, fallthrough */
+    case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
+      return plan->drop_hints;
+    // Drop Layout Tables if requested.
+    case HB_OT_TAG_GDEF:
+    case HB_OT_TAG_GPOS:
+    case HB_OT_TAG_GSUB:
+      return plan->drop_layout;
+    // Drop these tables below by default, list pulled
+    // from fontTools:
+    case HB_TAG ('B', 'A', 'S', 'E'):
+    case HB_TAG ('J', 'S', 'T', 'F'):
+    case HB_TAG ('D', 'S', 'I', 'G'):
+    case HB_TAG ('E', 'B', 'D', 'T'):
+    case HB_TAG ('E', 'B', 'L', 'C'):
+    case HB_TAG ('E', 'B', 'S', 'C'):
+    case HB_TAG ('S', 'V', 'G', ' '):
+    case HB_TAG ('P', 'C', 'L', 'T'):
+    case HB_TAG ('L', 'T', 'S', 'H'):
+    // Graphite tables:
+    case HB_TAG ('F', 'e', 'a', 't'):
+    case HB_TAG ('G', 'l', 'a', 't'):
+    case HB_TAG ('G', 'l', 'o', 'c'):
+    case HB_TAG ('S', 'i', 'l', 'f'):
+    case HB_TAG ('S', 'i', 'l', 'l'):
+    // Colour
+    case HB_TAG ('s', 'b', 'i', 'x'):
+      return true;
+    default:
+      return false;
+  }
+}
+
+/**
+ * hb_subset:
+ * @source: font face data to be subset.
+ * @input: input to use for the subsetting.
+ *
+ * Subsets a font according to provided input.
+ **/
+hb_face_t *
+hb_subset (hb_face_t *source,
+           hb_subset_input_t *input)
+{
+  if (unlikely (!input || !source)) return hb_face_get_empty ();
+
+  hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
+
+  hb_tag_t table_tags[32];
+  unsigned int offset = 0, count;
+  bool success = true;
+  do {
+    count = ARRAY_LENGTH (table_tags);
+    hb_face_get_table_tags (source, offset, &count, table_tags);
+    for (unsigned int i = 0; i < count; i++)
+    {
+      hb_tag_t tag = table_tags[i];
+      if (_should_drop_table (plan, tag))
+      {
+        DEBUG_MSG(SUBSET, nullptr, "drop %c%c%c%c", HB_UNTAG (tag));
+        continue;
+      }
+      success = success && _subset_table (plan, tag);
+    }
+    offset += count;
+  } while (success && count == ARRAY_LENGTH (table_tags));
+
+  hb_face_t *result = success ? hb_face_reference (plan->dest) : hb_face_get_empty ();
+  hb_subset_plan_destroy (plan);
+  return result;
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.h	Tue Mar 26 09:05:10 2019 -0400
@@ -32,20 +32,6 @@
 HB_BEGIN_DECLS
 
 /*
- * hb_subset_profile_t
- * Things that change based on target environment, e.g. OS.
- * Threadsafe for multiple concurrent subset operations.
- */
-
-typedef struct hb_subset_profile_t hb_subset_profile_t;
-
-HB_EXTERN hb_subset_profile_t *
-hb_subset_profile_create (void);
-
-HB_EXTERN void
-hb_subset_profile_destroy (hb_subset_profile_t *profile);
-
-/*
  * hb_subset_input_t
  *
  * Things that change based on the input. Characters to keep, etc.
@@ -68,21 +54,28 @@
 HB_EXTERN hb_set_t *
 hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
 
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_hints (hb_subset_input_t *subset_input);
+HB_EXTERN void
+hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
+                                hb_bool_t drop_hints);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input);
 
-HB_EXTERN hb_bool_t *
-hb_subset_input_drop_ot_layout (hb_subset_input_t *subset_input);
+HB_EXTERN void
+hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
+                                 hb_bool_t drop_layout);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input);
 
-/* hb_subset() */
+HB_EXTERN void
+hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
+        hb_bool_t desubroutinize);
+HB_EXTERN hb_bool_t
+hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
+
+/* hb_subset () */
 HB_EXTERN hb_face_t *
-hb_subset (hb_face_t *source,
-           hb_subset_profile_t *profile,
-           hb_subset_input_t *input);
+hb_subset (hb_face_t *source, hb_subset_input_t *input);
 
-/* hb_subset_get_all_codepoints */
-HB_EXTERN void
-hb_subset_get_all_codepoints (hb_face_t *source, hb_set_t *out);
 
 HB_END_DECLS
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-subset.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger, Roderick Sheeter
+ */
+
+#ifndef HB_SUBSET_HH
+#define HB_SUBSET_HH
+
+
+#include "hb.hh"
+
+#include "hb-subset.h"
+
+#include "hb-machinery.hh"
+#include "hb-subset-input.hh"
+#include "hb-subset-plan.hh"
+
+struct hb_subset_context_t :
+       hb_dispatch_context_t<hb_subset_context_t, bool, HB_DEBUG_SUBSET>
+{
+  const char *get_name () { return "SUBSET"; }
+  template <typename T>
+  bool dispatch (const T &obj) { return obj.subset (this); }
+  static bool default_return_value () { return true; }
+
+  hb_subset_plan_t *plan;
+  hb_serialize_context_t *serializer;
+  unsigned int debug_depth;
+
+  hb_subset_context_t (hb_subset_plan_t *plan_,
+                       hb_serialize_context_t *serializer_) :
+                        plan (plan_),
+                        serializer (serializer_),
+                        debug_depth (0) {}
+};
+
+
+#endif /* HB_SUBSET_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -14,9 +14,9 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
 
-#include "hb-unicode-private.hh"
+#include "hb-machinery.hh"
 
 #include "ucdn.h"
 
@@ -181,15 +181,6 @@
     return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode);
 }
 
-static unsigned int
-hb_ucdn_eastasian_width(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                        hb_codepoint_t unicode,
-                        void *user_data HB_UNUSED)
-{
-    int w = ucdn_get_east_asian_width(unicode);
-    return (w == UCDN_EAST_ASIAN_F || w == UCDN_EAST_ASIAN_W) ? 2 : 1;
-}
-
 static hb_unicode_general_category_t
 hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED,
                          hb_codepoint_t unicode,
@@ -230,56 +221,48 @@
     return ucdn_decompose(ab, a, b);
 }
 
-static unsigned int
-hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED,
-                                hb_codepoint_t u, hb_codepoint_t *decomposed,
-                                void *user_data HB_UNUSED)
+
+#if HB_USE_ATEXIT
+static void free_static_ucdn_funcs ();
+#endif
+
+static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucdn_unicode_funcs_lazy_loader_t>
 {
-    return ucdn_compat_decompose(u, decomposed);
-}
-
-static hb_unicode_funcs_t *static_ucdn_funcs = nullptr;
+  static hb_unicode_funcs_t *create ()
+  {
+    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
 
-#ifdef HB_USE_ATEXIT
+    hb_unicode_funcs_set_combining_class_func (funcs, hb_ucdn_combining_class, nullptr, nullptr);
+    hb_unicode_funcs_set_general_category_func (funcs, hb_ucdn_general_category, nullptr, nullptr);
+    hb_unicode_funcs_set_mirroring_func (funcs, hb_ucdn_mirroring, nullptr, nullptr);
+    hb_unicode_funcs_set_script_func (funcs, hb_ucdn_script, nullptr, nullptr);
+    hb_unicode_funcs_set_compose_func (funcs, hb_ucdn_compose, nullptr, nullptr);
+    hb_unicode_funcs_set_decompose_func (funcs, hb_ucdn_decompose, nullptr, nullptr);
+
+    hb_unicode_funcs_make_immutable (funcs);
+
+#if HB_USE_ATEXIT
+    atexit (free_static_ucdn_funcs);
+#endif
+
+    return funcs;
+  }
+} static_ucdn_funcs;
+
+#if HB_USE_ATEXIT
 static
-void free_static_ucdn_funcs (void)
+void free_static_ucdn_funcs ()
 {
-retry:
-  hb_unicode_funcs_t *ucdn_funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
-  if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, ucdn_funcs, nullptr))
-    goto retry;
-
-  hb_unicode_funcs_destroy (ucdn_funcs);
+  static_ucdn_funcs.free_instance ();
 }
 #endif
 
 extern "C" HB_INTERNAL
 hb_unicode_funcs_t *
-hb_ucdn_get_unicode_funcs (void)
-{
-retry:
-  hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs);
-
-  if (unlikely (!funcs))
-  {
-    funcs = hb_unicode_funcs_create (nullptr);
-
-#define HB_UNICODE_FUNC_IMPLEMENT(name) \
-    hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr);
-      HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
+hb_ucdn_get_unicode_funcs ();
 
-    hb_unicode_funcs_make_immutable (funcs);
-
-    if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) {
-      hb_unicode_funcs_destroy (funcs);
-      goto retry;
-    }
-
-#ifdef HB_USE_ATEXIT
-    atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */
-#endif
-  };
-
-  return hb_unicode_funcs_reference (funcs);
+hb_unicode_funcs_t *
+hb_ucdn_get_unicode_funcs ()
+{
+  return static_ucdn_funcs.get_unconst ();
 }
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn/ucdn.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ucdn/ucdn.h	Tue Mar 26 09:05:10 2019 -0400
@@ -456,8 +456,6 @@
  */
 int ucdn_compose(uint32_t *code, uint32_t a, uint32_t b);
 
-#ifdef __cplusplus
-}
-#endif
+HB_END_HEADER
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode-emoji-table.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,110 @@
+/* == Start of generated table == */
+/*
+ * The following tables are generated by running:
+ *
+ *   ./gen-emoji-table.py emoji-data.txt
+ *
+ * on file with this header:
+ *
+ * # emoji-data.txt
+ * # Date: 2018-02-07, 07:55:18 GMT
+ * # © 2018 Unicode®, Inc.
+ * # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
+ * # For terms of use, see http://www.unicode.org/terms_of_use.html
+ * #
+ * # Emoji Data for UTS #51
+ * # Version: 11.0
+ * #
+ * # For documentation and usage, see http://www.unicode.org/reports/tr51
+ */
+
+#ifndef HB_UNICODE_EMOJI_TABLE_HH
+#define HB_UNICODE_EMOJI_TABLE_HH
+
+#include "hb-unicode.hh"
+
+
+static const struct hb_unicode_range_t _hb_unicode_emoji_Extended_Pictographic_table[] =
+{
+  {0x00A9, 0x00A9},
+  {0x00AE, 0x00AE},
+  {0x203C, 0x203C},
+  {0x2049, 0x2049},
+  {0x2122, 0x2122},
+  {0x2139, 0x2139},
+  {0x2194, 0x2199},
+  {0x21A9, 0x21AA},
+  {0x231A, 0x231B},
+  {0x2328, 0x2328},
+  {0x2388, 0x2388},
+  {0x23CF, 0x23CF},
+  {0x23E9, 0x23F3},
+  {0x23F8, 0x23FA},
+  {0x24C2, 0x24C2},
+  {0x25AA, 0x25AB},
+  {0x25B6, 0x25B6},
+  {0x25C0, 0x25C0},
+  {0x25FB, 0x25FE},
+  {0x2600, 0x2605},
+  {0x2607, 0x2612},
+  {0x2614, 0x2685},
+  {0x2690, 0x2705},
+  {0x2708, 0x2712},
+  {0x2714, 0x2714},
+  {0x2716, 0x2716},
+  {0x271D, 0x271D},
+  {0x2721, 0x2721},
+  {0x2728, 0x2728},
+  {0x2733, 0x2734},
+  {0x2744, 0x2744},
+  {0x2747, 0x2747},
+  {0x274C, 0x274C},
+  {0x274E, 0x274E},
+  {0x2753, 0x2755},
+  {0x2757, 0x2757},
+  {0x2763, 0x2767},
+  {0x2795, 0x2797},
+  {0x27A1, 0x27A1},
+  {0x27B0, 0x27B0},
+  {0x27BF, 0x27BF},
+  {0x2934, 0x2935},
+  {0x2B05, 0x2B07},
+  {0x2B1B, 0x2B1C},
+  {0x2B50, 0x2B50},
+  {0x2B55, 0x2B55},
+  {0x3030, 0x3030},
+  {0x303D, 0x303D},
+  {0x3297, 0x3297},
+  {0x3299, 0x3299},
+  {0x1F000, 0x1F0FF},
+  {0x1F10D, 0x1F10F},
+  {0x1F12F, 0x1F12F},
+  {0x1F16C, 0x1F171},
+  {0x1F17E, 0x1F17F},
+  {0x1F18E, 0x1F18E},
+  {0x1F191, 0x1F19A},
+  {0x1F1AD, 0x1F1E5},
+  {0x1F201, 0x1F20F},
+  {0x1F21A, 0x1F21A},
+  {0x1F22F, 0x1F22F},
+  {0x1F232, 0x1F23A},
+  {0x1F23C, 0x1F23F},
+  {0x1F249, 0x1F3FA},
+  {0x1F400, 0x1F53D},
+  {0x1F546, 0x1F64F},
+  {0x1F680, 0x1F6FF},
+  {0x1F774, 0x1F77F},
+  {0x1F7D5, 0x1F7FF},
+  {0x1F80C, 0x1F80F},
+  {0x1F848, 0x1F84F},
+  {0x1F85A, 0x1F85F},
+  {0x1F888, 0x1F88F},
+  {0x1F8AE, 0x1F8FF},
+  {0x1F90C, 0x1F93A},
+  {0x1F93C, 0x1F945},
+  {0x1F947, 0x1FFFD},
+};
+
+#endif /* HB_UNICODE_EMOJI_TABLE_HH */
+
+/* == End of generated table == */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/*
- * Copyright © 2009  Red Hat, Inc.
- * Copyright © 2011  Codethink Limited
- * Copyright © 2010,2011,2012  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Red Hat Author(s): Behdad Esfahbod
- * Codethink Author(s): Ryan Lortie
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_UNICODE_PRIVATE_HH
-#define HB_UNICODE_PRIVATE_HH
-
-#include "hb-private.hh"
-#include "hb-object-private.hh"
-
-
-extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
-
-/*
- * hb_unicode_funcs_t
- */
-
-#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
-  HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
-  HB_UNICODE_FUNC_IMPLEMENT (general_category) \
-  HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
-  HB_UNICODE_FUNC_IMPLEMENT (script) \
-  HB_UNICODE_FUNC_IMPLEMENT (compose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose) \
-  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
-  /* ^--- Add new callbacks here */
-
-/* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
-#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
-  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
-  HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
-  /* ^--- Add new simple callbacks here */
-
-struct hb_unicode_funcs_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_unicode_funcs_t *parent;
-
-  bool immutable;
-
-#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
-  inline return_type name (hb_codepoint_t unicode) { return func.name (this, unicode, user_data.name); }
-HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
-#undef HB_UNICODE_FUNC_IMPLEMENT
-
-  inline hb_bool_t compose (hb_codepoint_t a, hb_codepoint_t b,
-                            hb_codepoint_t *ab)
-  {
-    *ab = 0;
-    if (unlikely (!a || !b)) return false;
-    return func.compose (this, a, b, ab, user_data.compose);
-  }
-
-  inline hb_bool_t decompose (hb_codepoint_t ab,
-                              hb_codepoint_t *a, hb_codepoint_t *b)
-  {
-    *a = ab; *b = 0;
-    return func.decompose (this, ab, a, b, user_data.decompose);
-  }
-
-  inline unsigned int decompose_compatibility (hb_codepoint_t  u,
-                                               hb_codepoint_t *decomposed)
-  {
-    unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
-    if (ret == 1 && u == decomposed[0]) {
-      decomposed[0] = 0;
-      return 0;
-    }
-    decomposed[ret] = 0;
-    return ret;
-  }
-
-
-  inline unsigned int
-  modified_combining_class (hb_codepoint_t unicode)
-  {
-    /* XXX This hack belongs to the Myanmar shaper. */
-    if (unlikely (unicode == 0x1037u)) unicode = 0x103Au;
-
-    /* XXX This hack belongs to the USE shaper (for Tai Tham):
-     * Reorder SAKOT to ensure it comes after any tone marks. */
-    if (unlikely (unicode == 0x1A60u)) return 254;
-
-    /* XXX This hack belongs to the Tibetan shaper:
-     * Reorder PADMA to ensure it comes after any vowel marks. */
-    if (unlikely (unicode == 0x0FC6u)) return 254;
-    /* Reorder TSA -PHRU to reorder before U+0F74 */
-    if (unlikely (unicode == 0x0F39u)) return 127;
-
-    return _hb_modified_combining_class[combining_class (unicode)];
-  }
-
-  static inline hb_bool_t
-  is_variation_selector (hb_codepoint_t unicode)
-  {
-    /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
-     * Arabic shaper.  No need to match them here. */
-    return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
-                                   0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
-                                   0xE0100u, 0xE01EFu));  /* VARIATION SELECTOR-17..256 */
-  }
-
-  /* Default_Ignorable codepoints:
-   *
-   * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
-   * we do NOT want to hide them, as the way Uniscribe has implemented them
-   * is with regular spacing glyphs, and that's the way fonts are made to work.
-   * As such, we make exceptions for those four.
-   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
-   *
-   * Unicode 7.0:
-   * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
-   * 00AD          # Cf       SOFT HYPHEN
-   * 034F          # Mn       COMBINING GRAPHEME JOINER
-   * 061C          # Cf       ARABIC LETTER MARK
-   * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
-   * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
-   * 180B..180D    # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
-   * 180E          # Cf       MONGOLIAN VOWEL SEPARATOR
-   * 200B..200F    # Cf   [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
-   * 202A..202E    # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
-   * 2060..2064    # Cf   [5] WORD JOINER..INVISIBLE PLUS
-   * 2065          # Cn       <reserved-2065>
-   * 2066..206F    # Cf  [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
-   * 3164          # Lo       HANGUL FILLER
-   * FE00..FE0F    # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
-   * FEFF          # Cf       ZERO WIDTH NO-BREAK SPACE
-   * FFA0          # Lo       HALFWIDTH HANGUL FILLER
-   * FFF0..FFF8    # Cn   [9] <reserved-FFF0>..<reserved-FFF8>
-   * 1BCA0..1BCA3  # Cf   [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
-   * 1D173..1D17A  # Cf   [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
-   * E0000         # Cn       <reserved-E0000>
-   * E0001         # Cf       LANGUAGE TAG
-   * E0002..E001F  # Cn  [30] <reserved-E0002>..<reserved-E001F>
-   * E0020..E007F  # Cf  [96] TAG SPACE..CANCEL TAG
-   * E0080..E00FF  # Cn [128] <reserved-E0080>..<reserved-E00FF>
-   * E0100..E01EF  # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-   * E01F0..E0FFF  # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
-   */
-  static inline hb_bool_t
-  is_default_ignorable (hb_codepoint_t ch)
-  {
-    hb_codepoint_t plane = ch >> 16;
-    if (likely (plane == 0))
-    {
-      /* BMP */
-      hb_codepoint_t page = ch >> 8;
-      switch (page) {
-        case 0x00: return unlikely (ch == 0x00ADu);
-        case 0x03: return unlikely (ch == 0x034Fu);
-        case 0x06: return unlikely (ch == 0x061Cu);
-        case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u);
-        case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu);
-        case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu,
-                                            0x202Au, 0x202Eu,
-                                            0x2060u, 0x206Fu);
-        case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
-        case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
-        default: return false;
-      }
-    }
-    else
-    {
-      /* Other planes */
-      switch (plane) {
-        case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au);
-        case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
-        default: return false;
-      }
-    }
-  }
-
-  /* Space estimates based on:
-   * https://unicode.org/charts/PDF/U2000.pdf
-   * https://docs.microsoft.com/en-us/typography/develop/character-design-standards/whitespace
-   */
-  enum space_t {
-    NOT_SPACE = 0,
-    SPACE_EM   = 1,
-    SPACE_EM_2 = 2,
-    SPACE_EM_3 = 3,
-    SPACE_EM_4 = 4,
-    SPACE_EM_5 = 5,
-    SPACE_EM_6 = 6,
-    SPACE_EM_16 = 16,
-    SPACE_4_EM_18,      /* 4/18th of an EM! */
-    SPACE,
-    SPACE_FIGURE,
-    SPACE_PUNCTUATION,
-    SPACE_NARROW,
-  };
-  static inline space_t
-  space_fallback_type (hb_codepoint_t u)
-  {
-    switch (u)
-    {
-      /* All GC=Zs chars that can use a fallback. */
-      default:      return NOT_SPACE;   /* U+1680 OGHAM SPACE MARK */
-      case 0x0020u: return SPACE;       /* U+0020 SPACE */
-      case 0x00A0u: return SPACE;       /* U+00A0 NO-BREAK SPACE */
-      case 0x2000u: return SPACE_EM_2;  /* U+2000 EN QUAD */
-      case 0x2001u: return SPACE_EM;    /* U+2001 EM QUAD */
-      case 0x2002u: return SPACE_EM_2;  /* U+2002 EN SPACE */
-      case 0x2003u: return SPACE_EM;    /* U+2003 EM SPACE */
-      case 0x2004u: return SPACE_EM_3;  /* U+2004 THREE-PER-EM SPACE */
-      case 0x2005u: return SPACE_EM_4;  /* U+2005 FOUR-PER-EM SPACE */
-      case 0x2006u: return SPACE_EM_6;  /* U+2006 SIX-PER-EM SPACE */
-      case 0x2007u: return SPACE_FIGURE;        /* U+2007 FIGURE SPACE */
-      case 0x2008u: return SPACE_PUNCTUATION;   /* U+2008 PUNCTUATION SPACE */
-      case 0x2009u: return SPACE_EM_5;          /* U+2009 THIN SPACE */
-      case 0x200Au: return SPACE_EM_16;         /* U+200A HAIR SPACE */
-      case 0x202Fu: return SPACE_NARROW;        /* U+202F NARROW NO-BREAK SPACE */
-      case 0x205Fu: return SPACE_4_EM_18;       /* U+205F MEDIUM MATHEMATICAL SPACE */
-      case 0x3000u: return SPACE_EM;            /* U+3000 IDEOGRAPHIC SPACE */
-    }
-  }
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } func;
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) void *name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } user_data;
-
-  struct {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
-    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_UNICODE_FUNC_IMPLEMENT
-  } destroy;
-};
-
-
-extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
-
-
-/* Modified combining marks */
-
-/* Hebrew
- *
- * We permute the "fixed-position" classes 10-26 into the order
- * described in the SBL Hebrew manual:
- *
- * https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
- *
- * (as recommended by:
- *  https://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering/msg22823/)
- *
- * More details here:
- * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC10 22 /* sheva */
-#define HB_MODIFIED_COMBINING_CLASS_CCC11 15 /* hataf segol */
-#define HB_MODIFIED_COMBINING_CLASS_CCC12 16 /* hataf patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC13 17 /* hataf qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC14 23 /* hiriq */
-#define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
-#define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
-#define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
-#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
-#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
-#define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
-#define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
-#define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */
-#define HB_MODIFIED_COMBINING_CLASS_CCC23 13 /* rafe */
-#define HB_MODIFIED_COMBINING_CLASS_CCC24 10 /* shin dot */
-#define HB_MODIFIED_COMBINING_CLASS_CCC25 11 /* sin dot */
-#define HB_MODIFIED_COMBINING_CLASS_CCC26 26 /* point varika */
-
-/*
- * Arabic
- *
- * Modify to move Shadda (ccc=33) before other marks.  See:
- * https://unicode.org/faq/normalization.html#8
- * https://unicode.org/faq/normalization.html#9
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC29 30 /* kasratan */
-#define HB_MODIFIED_COMBINING_CLASS_CCC30 31 /* fatha */
-#define HB_MODIFIED_COMBINING_CLASS_CCC31 32 /* damma */
-#define HB_MODIFIED_COMBINING_CLASS_CCC32 33 /* kasra */
-#define HB_MODIFIED_COMBINING_CLASS_CCC33 27 /* shadda */
-#define HB_MODIFIED_COMBINING_CLASS_CCC34 34 /* sukun */
-#define HB_MODIFIED_COMBINING_CLASS_CCC35 35 /* superscript alef */
-
-/* Syriac */
-#define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
-
-/* Telugu
- *
- * Modify Telugu length marks (ccc=84, ccc=91).
- * These are the only matras in the main Indic scripts range that have
- * a non-zero ccc.  That makes them reorder with the Halant that is
- * ccc=9.  Just zero them, we don't need them in our Indic shaper.
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
-#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
-
-/* Thai
- *
- * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
- * Assign 3, which is unassigned otherwise.
- * Uniscribe does this reordering too.
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
-#define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */
-
-/* Lao */
-#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
-#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
-
-/* Tibetan
- *
- * In case of multiple vowel-signs, use u first (but after achung)
- * this allows Dzongkha multi-vowel shortcuts to render correctly
- */
-#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
-#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */
-#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */
-
-/* Misc */
-
-#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \
-        (FLAG_UNSAFE (gen_cat) & \
-         (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-          FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
-          FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
-
-#define HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL(gen_cat) \
-        (FLAG_UNSAFE (gen_cat) & \
-         (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
-          FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
-          FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL)))
-
-#endif /* HB_UNICODE_PRIVATE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -28,10 +28,24 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-private.hh"
+#include "hb.hh"
+
+#include "hb-unicode.hh"
+
 
-#include "hb-unicode-private.hh"
-
+/**
+ * SECTION: hb-unicode
+ * @title: hb-unicode
+ * @short_description: Unicode character property access
+ * @include: hb.h
+ *
+ * Unicode functions are used to access Unicode character properties.
+ * Client can pass its own Unicode functions to HarfBuzz, or access
+ * the built-in Unicode functions that come with HarfBuzz.
+ *
+ * With the Unicode functions, one can query variour Unicode character
+ * properties, such as General Category, Script, Combining Class, etc.
+ **/
 
 
 /*
@@ -109,40 +123,23 @@
 }
 
 
-#define HB_UNICODE_FUNCS_IMPLEMENT_SET \
-  HB_UNICODE_FUNCS_IMPLEMENT (glib) \
-  HB_UNICODE_FUNCS_IMPLEMENT (icu) \
-  HB_UNICODE_FUNCS_IMPLEMENT (ucdn) \
-  HB_UNICODE_FUNCS_IMPLEMENT (nil) \
-  /* ^--- Add new callbacks before nil */
-
-#define hb_nil_get_unicode_funcs hb_unicode_funcs_get_empty
-
-/* Prototype them all */
-#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
-extern "C" hb_unicode_funcs_t *hb_##set##_get_unicode_funcs (void);
-HB_UNICODE_FUNCS_IMPLEMENT_SET
-#undef HB_UNICODE_FUNCS_IMPLEMENT
-
+extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs ();
+extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs ();
+extern "C" hb_unicode_funcs_t *hb_ucdn_get_unicode_funcs ();
 
 hb_unicode_funcs_t *
-hb_unicode_funcs_get_default (void)
+hb_unicode_funcs_get_default ()
 {
-#define HB_UNICODE_FUNCS_IMPLEMENT(set) \
-  return hb_##set##_get_unicode_funcs ();
-
 #if defined(HAVE_UCDN)
-  HB_UNICODE_FUNCS_IMPLEMENT(ucdn)
+  return hb_ucdn_get_unicode_funcs ();
 #elif defined(HAVE_GLIB)
-  HB_UNICODE_FUNCS_IMPLEMENT(glib)
+  return hb_glib_get_unicode_funcs ();
 #elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
-  HB_UNICODE_FUNCS_IMPLEMENT(icu)
+  return hb_icu_get_unicode_funcs ();
 #else
 #define HB_UNICODE_FUNCS_NIL 1
-  HB_UNICODE_FUNCS_IMPLEMENT(nil)
+  return hb_unicode_funcs_get_empty ();
 #endif
-
-#undef HB_UNICODE_FUNCS_IMPLEMENT
 }
 
 #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
@@ -185,11 +182,11 @@
 }
 
 
-const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
   nullptr, /* parent */
-  true, /* immutable */
   {
 #define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_nil,
     HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
@@ -207,9 +204,9 @@
  * Since: 0.9.2
  **/
 hb_unicode_funcs_t *
-hb_unicode_funcs_get_empty (void)
+hb_unicode_funcs_get_empty ()
 {
-  return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
+  return const_cast<hb_unicode_funcs_t *> (&Null(hb_unicode_funcs_t));
 }
 
 /**
@@ -305,10 +302,10 @@
 void
 hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
 {
-  if (unlikely (hb_object_is_inert (ufuncs)))
+  if (hb_object_is_immutable (ufuncs))
     return;
 
-  ufuncs->immutable = true;
+  hb_object_make_immutable (ufuncs);
 }
 
 /**
@@ -324,7 +321,7 @@
 hb_bool_t
 hb_unicode_funcs_is_immutable (hb_unicode_funcs_t *ufuncs)
 {
-  return ufuncs->immutable;
+  return hb_object_is_immutable (ufuncs);
 }
 
 /**
@@ -352,7 +349,7 @@
                                     void                           *user_data,  \
                                     hb_destroy_func_t               destroy)    \
 {                                                                               \
-  if (ufuncs->immutable)                                                        \
+  if (hb_object_is_immutable (ufuncs))                                          \
     return;                                                                     \
                                                                                 \
   if (ufuncs->destroy.name)                                                     \
@@ -439,6 +436,7 @@
  * Return value:
  *
  * Since: 0.9.2
+ * Deprecated: 2.0.0
  **/
 unsigned int
 hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
@@ -449,7 +447,7 @@
 }
 
 
-/* See hb-unicode-private.hh for details. */
+/* See hb-unicode.hh for details. */
 const uint8_t
 _hb_modified_combining_class[256] =
 {
@@ -561,3 +559,19 @@
   241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
   255, /* HB_UNICODE_COMBINING_CLASS_INVALID */
 };
+
+
+/*
+ * Emoji
+ */
+
+#include "hb-unicode-emoji-table.hh"
+
+bool
+_hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp)
+{
+  return hb_bsearch (&cp, _hb_unicode_emoji_Extended_Pictographic_table,
+                     ARRAY_LENGTH (_hb_unicode_emoji_Extended_Pictographic_table),
+                     sizeof (hb_unicode_range_t),
+                     hb_unicode_range_t::cmp);
+}
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.h	Tue Mar 26 09:05:10 2019 -0400
@@ -40,6 +40,14 @@
 HB_BEGIN_DECLS
 
 
+/**
+ * HB_UNICODE_MAX
+ *
+ * Since: 1.9.0
+ **/
+#define HB_UNICODE_MAX 0x10FFFFu
+
+
 /* hb_unicode_general_category_t */
 
 /* Unicode Character Database property: General_Category (gc) */
@@ -222,9 +230,6 @@
 typedef hb_unicode_combining_class_t    (*hb_unicode_combining_class_func_t)    (hb_unicode_funcs_t *ufuncs,
                                                                                  hb_codepoint_t      unicode,
                                                                                  void               *user_data);
-typedef unsigned int                    (*hb_unicode_eastasian_width_func_t)    (hb_unicode_funcs_t *ufuncs,
-                                                                                 hb_codepoint_t      unicode,
-                                                                                 void               *user_data);
 typedef hb_unicode_general_category_t   (*hb_unicode_general_category_func_t)   (hb_unicode_funcs_t *ufuncs,
                                                                                  hb_codepoint_t      unicode,
                                                                                  void               *user_data);
@@ -246,32 +251,6 @@
                                                                                  hb_codepoint_t     *b,
                                                                                  void               *user_data);
 
-/**
- * hb_unicode_decompose_compatibility_func_t:
- * @ufuncs: a Unicode function structure
- * @u: codepoint to decompose
- * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into
- * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func()
- *
- * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed.
- * The complete length of the decomposition will be returned.
- *
- * If @u has no compatibility decomposition, zero should be returned.
- *
- * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any
- * compatibility decomposition plus an terminating value of 0.  Consequently, @decompose must be allocated by the caller to be at least this length.  Implementations
- * of this function type must ensure that they do not write past the provided array.
- *
- * Return value: number of codepoints in the full compatibility decomposition of @u, or 0 if no decomposition available.
- */
-typedef unsigned int                    (*hb_unicode_decompose_compatibility_func_t)    (hb_unicode_funcs_t *ufuncs,
-                                                                                         hb_codepoint_t      u,
-                                                                                         hb_codepoint_t     *decomposed,
-                                                                                         void               *user_data);
-
-/* See Unicode 6.1 for details on the maximum decomposition length. */
-#define HB_UNICODE_MAX_DECOMPOSITION_LEN (18+1) /* codepoints */
-
 /* setters */
 
 /**
@@ -291,22 +270,6 @@
                                            void *user_data, hb_destroy_func_t destroy);
 
 /**
- * hb_unicode_funcs_set_eastasian_width_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
-                                           hb_unicode_eastasian_width_func_t func,
-                                           void *user_data, hb_destroy_func_t destroy);
-
-/**
  * hb_unicode_funcs_set_general_category_func:
  * @ufuncs: a Unicode function structure
  * @func: (closure user_data) (destroy destroy) (scope notified):
@@ -386,22 +349,6 @@
                                      hb_unicode_decompose_func_t func,
                                      void *user_data, hb_destroy_func_t destroy);
 
-/**
- * hb_unicode_funcs_set_decompose_compatibility_func:
- * @ufuncs: a Unicode function structure
- * @func: (closure user_data) (destroy destroy) (scope notified):
- * @user_data:
- * @destroy:
- *
- *
- *
- * Since: 0.9.2
- **/
-HB_EXTERN void
-hb_unicode_funcs_set_decompose_compatibility_func (hb_unicode_funcs_t *ufuncs,
-                                                   hb_unicode_decompose_compatibility_func_t func,
-                                                   void *user_data, hb_destroy_func_t destroy);
-
 /* accessors */
 
 /**
@@ -414,15 +361,6 @@
                             hb_codepoint_t unicode);
 
 /**
- * hb_unicode_eastasian_width:
- *
- * Since: 0.9.2
- **/
-HB_EXTERN unsigned int
-hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs,
-                            hb_codepoint_t unicode);
-
-/**
  * hb_unicode_general_category:
  *
  * Since: 0.9.2
@@ -461,11 +399,6 @@
                       hb_codepoint_t     *a,
                       hb_codepoint_t     *b);
 
-HB_EXTERN unsigned int
-hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
-                                    hb_codepoint_t      u,
-                                    hb_codepoint_t     *decomposed);
-
 HB_END_DECLS
 
 #endif /* HB_UNICODE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-unicode.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2009  Red Hat, Inc.
+ * Copyright © 2011  Codethink Limited
+ * Copyright © 2010,2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Codethink Author(s): Ryan Lortie
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_UNICODE_HH
+#define HB_UNICODE_HH
+
+#include "hb.hh"
+
+
+extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
+
+/*
+ * hb_unicode_funcs_t
+ */
+
+#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
+  HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
+  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
+  HB_UNICODE_FUNC_IMPLEMENT (general_category) \
+  HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
+  HB_UNICODE_FUNC_IMPLEMENT (script) \
+  HB_UNICODE_FUNC_IMPLEMENT (compose) \
+  HB_UNICODE_FUNC_IMPLEMENT (decompose) \
+  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
+  /* ^--- Add new callbacks here */
+
+/* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
+#define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
+  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
+  HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
+  /* ^--- Add new simple callbacks here */
+
+struct hb_unicode_funcs_t
+{
+  hb_object_header_t header;
+
+  hb_unicode_funcs_t *parent;
+
+#define HB_UNICODE_FUNC_IMPLEMENT(return_type, name) \
+  return_type name (hb_codepoint_t unicode) { return func.name (this, unicode, user_data.name); }
+HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
+#undef HB_UNICODE_FUNC_IMPLEMENT
+
+  hb_bool_t compose (hb_codepoint_t a, hb_codepoint_t b,
+                     hb_codepoint_t *ab)
+  {
+    *ab = 0;
+    if (unlikely (!a || !b)) return false;
+    return func.compose (this, a, b, ab, user_data.compose);
+  }
+
+  hb_bool_t decompose (hb_codepoint_t ab,
+                       hb_codepoint_t *a, hb_codepoint_t *b)
+  {
+    *a = ab; *b = 0;
+    return func.decompose (this, ab, a, b, user_data.decompose);
+  }
+
+  unsigned int decompose_compatibility (hb_codepoint_t  u,
+                                        hb_codepoint_t *decomposed)
+  {
+    unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
+    if (ret == 1 && u == decomposed[0]) {
+      decomposed[0] = 0;
+      return 0;
+    }
+    decomposed[ret] = 0;
+    return ret;
+  }
+
+  unsigned int
+  modified_combining_class (hb_codepoint_t u)
+  {
+    /* XXX This hack belongs to the Myanmar shaper. */
+    if (unlikely (u == 0x1037u)) u = 0x103Au;
+
+    /* XXX This hack belongs to the USE shaper (for Tai Tham):
+     * Reorder SAKOT to ensure it comes after any tone marks. */
+    if (unlikely (u == 0x1A60u)) return 254;
+
+    /* XXX This hack belongs to the Tibetan shaper:
+     * Reorder PADMA to ensure it comes after any vowel marks. */
+    if (unlikely (u == 0x0FC6u)) return 254;
+    /* Reorder TSA -PHRU to reorder before U+0F74 */
+    if (unlikely (u == 0x0F39u)) return 127;
+
+    return _hb_modified_combining_class[combining_class (u)];
+  }
+
+  static hb_bool_t
+  is_variation_selector (hb_codepoint_t unicode)
+  {
+    /* U+180B..180D MONGOLIAN FREE VARIATION SELECTORs are handled in the
+     * Arabic shaper.  No need to match them here. */
+    return unlikely (hb_in_ranges<hb_codepoint_t> (unicode,
+                                                   0xFE00u, 0xFE0Fu, /* VARIATION SELECTOR-1..16 */
+                                                   0xE0100u, 0xE01EFu));  /* VARIATION SELECTOR-17..256 */
+  }
+
+  /* Default_Ignorable codepoints:
+   *
+   * Note: While U+115F, U+1160, U+3164 and U+FFA0 are Default_Ignorable,
+   * we do NOT want to hide them, as the way Uniscribe has implemented them
+   * is with regular spacing glyphs, and that's the way fonts are made to work.
+   * As such, we make exceptions for those four.
+   * Also ignoring U+1BCA0..1BCA3. https://github.com/harfbuzz/harfbuzz/issues/503
+   *
+   * Unicode 7.0:
+   * $ grep '; Default_Ignorable_Code_Point ' DerivedCoreProperties.txt | sed 's/;.*#/#/'
+   * 00AD          # Cf       SOFT HYPHEN
+   * 034F          # Mn       COMBINING GRAPHEME JOINER
+   * 061C          # Cf       ARABIC LETTER MARK
+   * 115F..1160    # Lo   [2] HANGUL CHOSEONG FILLER..HANGUL JUNGSEONG FILLER
+   * 17B4..17B5    # Mn   [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+   * 180B..180D    # Mn   [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+   * 180E          # Cf       MONGOLIAN VOWEL SEPARATOR
+   * 200B..200F    # Cf   [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
+   * 202A..202E    # Cf   [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
+   * 2060..2064    # Cf   [5] WORD JOINER..INVISIBLE PLUS
+   * 2065          # Cn       <reserved-2065>
+   * 2066..206F    # Cf  [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
+   * 3164          # Lo       HANGUL FILLER
+   * FE00..FE0F    # Mn  [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
+   * FEFF          # Cf       ZERO WIDTH NO-BREAK SPACE
+   * FFA0          # Lo       HALFWIDTH HANGUL FILLER
+   * FFF0..FFF8    # Cn   [9] <reserved-FFF0>..<reserved-FFF8>
+   * 1BCA0..1BCA3  # Cf   [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
+   * 1D173..1D17A  # Cf   [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
+   * E0000         # Cn       <reserved-E0000>
+   * E0001         # Cf       LANGUAGE TAG
+   * E0002..E001F  # Cn  [30] <reserved-E0002>..<reserved-E001F>
+   * E0020..E007F  # Cf  [96] TAG SPACE..CANCEL TAG
+   * E0080..E00FF  # Cn [128] <reserved-E0080>..<reserved-E00FF>
+   * E0100..E01EF  # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
+   * E01F0..E0FFF  # Cn [3600] <reserved-E01F0>..<reserved-E0FFF>
+   */
+  static hb_bool_t
+  is_default_ignorable (hb_codepoint_t ch)
+  {
+    hb_codepoint_t plane = ch >> 16;
+    if (likely (plane == 0))
+    {
+      /* BMP */
+      hb_codepoint_t page = ch >> 8;
+      switch (page) {
+        case 0x00: return unlikely (ch == 0x00ADu);
+        case 0x03: return unlikely (ch == 0x034Fu);
+        case 0x06: return unlikely (ch == 0x061Cu);
+        case 0x17: return hb_in_range<hb_codepoint_t> (ch, 0x17B4u, 0x17B5u);
+        case 0x18: return hb_in_range<hb_codepoint_t> (ch, 0x180Bu, 0x180Eu);
+        case 0x20: return hb_in_ranges<hb_codepoint_t> (ch, 0x200Bu, 0x200Fu,
+                                            0x202Au, 0x202Eu,
+                                            0x2060u, 0x206Fu);
+        case 0xFE: return hb_in_range<hb_codepoint_t> (ch, 0xFE00u, 0xFE0Fu) || ch == 0xFEFFu;
+        case 0xFF: return hb_in_range<hb_codepoint_t> (ch, 0xFFF0u, 0xFFF8u);
+        default: return false;
+      }
+    }
+    else
+    {
+      /* Other planes */
+      switch (plane) {
+        case 0x01: return hb_in_range<hb_codepoint_t> (ch, 0x1D173u, 0x1D17Au);
+        case 0x0E: return hb_in_range<hb_codepoint_t> (ch, 0xE0000u, 0xE0FFFu);
+        default: return false;
+      }
+    }
+  }
+
+  /* Space estimates based on:
+   * https://unicode.org/charts/PDF/U2000.pdf
+   * https://docs.microsoft.com/en-us/typography/develop/character-design-standards/whitespace
+   */
+  enum space_t {
+    NOT_SPACE = 0,
+    SPACE_EM   = 1,
+    SPACE_EM_2 = 2,
+    SPACE_EM_3 = 3,
+    SPACE_EM_4 = 4,
+    SPACE_EM_5 = 5,
+    SPACE_EM_6 = 6,
+    SPACE_EM_16 = 16,
+    SPACE_4_EM_18,      /* 4/18th of an EM! */
+    SPACE,
+    SPACE_FIGURE,
+    SPACE_PUNCTUATION,
+    SPACE_NARROW,
+  };
+  static space_t
+  space_fallback_type (hb_codepoint_t u)
+  {
+    switch (u)
+    {
+      /* All GC=Zs chars that can use a fallback. */
+      default:      return NOT_SPACE;   /* U+1680 OGHAM SPACE MARK */
+      case 0x0020u: return SPACE;       /* U+0020 SPACE */
+      case 0x00A0u: return SPACE;       /* U+00A0 NO-BREAK SPACE */
+      case 0x2000u: return SPACE_EM_2;  /* U+2000 EN QUAD */
+      case 0x2001u: return SPACE_EM;    /* U+2001 EM QUAD */
+      case 0x2002u: return SPACE_EM_2;  /* U+2002 EN SPACE */
+      case 0x2003u: return SPACE_EM;    /* U+2003 EM SPACE */
+      case 0x2004u: return SPACE_EM_3;  /* U+2004 THREE-PER-EM SPACE */
+      case 0x2005u: return SPACE_EM_4;  /* U+2005 FOUR-PER-EM SPACE */
+      case 0x2006u: return SPACE_EM_6;  /* U+2006 SIX-PER-EM SPACE */
+      case 0x2007u: return SPACE_FIGURE;        /* U+2007 FIGURE SPACE */
+      case 0x2008u: return SPACE_PUNCTUATION;   /* U+2008 PUNCTUATION SPACE */
+      case 0x2009u: return SPACE_EM_5;          /* U+2009 THIN SPACE */
+      case 0x200Au: return SPACE_EM_16;         /* U+200A HAIR SPACE */
+      case 0x202Fu: return SPACE_NARROW;        /* U+202F NARROW NO-BREAK SPACE */
+      case 0x205Fu: return SPACE_4_EM_18;       /* U+205F MEDIUM MATHEMATICAL SPACE */
+      case 0x3000u: return SPACE_EM;            /* U+3000 IDEOGRAPHIC SPACE */
+    }
+  }
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } func;
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) void *name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } user_data;
+
+  struct {
+#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+    HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_UNICODE_FUNC_IMPLEMENT
+  } destroy;
+};
+DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
+
+
+/*
+ * Modified combining marks
+ */
+
+/* Hebrew
+ *
+ * We permute the "fixed-position" classes 10-26 into the order
+ * described in the SBL Hebrew manual:
+ *
+ * https://www.sbl-site.org/Fonts/SBLHebrewUserManual1.5x.pdf
+ *
+ * (as recommended by:
+ *  https://forum.fontlab.com/archive-old-microsoft-volt-group/vista-and-diacritic-ordering/msg22823/)
+ *
+ * More details here:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=662055
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC10 22 /* sheva */
+#define HB_MODIFIED_COMBINING_CLASS_CCC11 15 /* hataf segol */
+#define HB_MODIFIED_COMBINING_CLASS_CCC12 16 /* hataf patah */
+#define HB_MODIFIED_COMBINING_CLASS_CCC13 17 /* hataf qamats */
+#define HB_MODIFIED_COMBINING_CLASS_CCC14 23 /* hiriq */
+#define HB_MODIFIED_COMBINING_CLASS_CCC15 18 /* tsere */
+#define HB_MODIFIED_COMBINING_CLASS_CCC16 19 /* segol */
+#define HB_MODIFIED_COMBINING_CLASS_CCC17 20 /* patah */
+#define HB_MODIFIED_COMBINING_CLASS_CCC18 21 /* qamats */
+#define HB_MODIFIED_COMBINING_CLASS_CCC19 14 /* holam */
+#define HB_MODIFIED_COMBINING_CLASS_CCC20 24 /* qubuts */
+#define HB_MODIFIED_COMBINING_CLASS_CCC21 12 /* dagesh */
+#define HB_MODIFIED_COMBINING_CLASS_CCC22 25 /* meteg */
+#define HB_MODIFIED_COMBINING_CLASS_CCC23 13 /* rafe */
+#define HB_MODIFIED_COMBINING_CLASS_CCC24 10 /* shin dot */
+#define HB_MODIFIED_COMBINING_CLASS_CCC25 11 /* sin dot */
+#define HB_MODIFIED_COMBINING_CLASS_CCC26 26 /* point varika */
+
+/*
+ * Arabic
+ *
+ * Modify to move Shadda (ccc=33) before other marks.  See:
+ * https://unicode.org/faq/normalization.html#8
+ * https://unicode.org/faq/normalization.html#9
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC27 28 /* fathatan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC28 29 /* dammatan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC29 30 /* kasratan */
+#define HB_MODIFIED_COMBINING_CLASS_CCC30 31 /* fatha */
+#define HB_MODIFIED_COMBINING_CLASS_CCC31 32 /* damma */
+#define HB_MODIFIED_COMBINING_CLASS_CCC32 33 /* kasra */
+#define HB_MODIFIED_COMBINING_CLASS_CCC33 27 /* shadda */
+#define HB_MODIFIED_COMBINING_CLASS_CCC34 34 /* sukun */
+#define HB_MODIFIED_COMBINING_CLASS_CCC35 35 /* superscript alef */
+
+/* Syriac */
+#define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
+
+/* Telugu
+ *
+ * Modify Telugu length marks (ccc=84, ccc=91).
+ * These are the only matras in the main Indic scripts range that have
+ * a non-zero ccc.  That makes them reorder with the Halant that is
+ * ccc=9.  Just zero them, we don't need them in our Indic shaper.
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
+#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
+
+/* Thai
+ *
+ * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
+ * Assign 3, which is unassigned otherwise.
+ * Uniscribe does this reordering too.
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
+#define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */
+
+/* Lao */
+#define HB_MODIFIED_COMBINING_CLASS_CCC118 118 /* sign u / sign uu */
+#define HB_MODIFIED_COMBINING_CLASS_CCC122 122 /* mai * */
+
+/* Tibetan
+ *
+ * In case of multiple vowel-signs, use u first (but after achung)
+ * this allows Dzongkha multi-vowel shortcuts to render correctly
+ */
+#define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */
+#define HB_MODIFIED_COMBINING_CLASS_CCC130 132 /* sign i */
+#define HB_MODIFIED_COMBINING_CLASS_CCC132 131 /* sign u */
+
+/* Misc */
+
+#define HB_UNICODE_GENERAL_CATEGORY_IS_MARK(gen_cat) \
+        (FLAG_UNSAFE (gen_cat) & \
+         (FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
+          FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
+          FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
+
+
+/*
+ * Ranges, used for bsearch tables.
+ */
+
+struct hb_unicode_range_t
+{
+  static int
+  cmp (const void *_key, const void *_item)
+  {
+    hb_codepoint_t cp = *((hb_codepoint_t *) _key);
+    const hb_unicode_range_t *range = (hb_unicode_range_t *) _item;
+
+    if (cp < range->start)
+      return -1;
+    else if (cp <= range->end)
+      return 0;
+    else
+      return +1;
+  }
+
+  hb_codepoint_t start;
+  hb_codepoint_t end;
+};
+
+/*
+ * Emoji.
+ */
+
+HB_INTERNAL bool
+_hb_unicode_is_emoji_Extended_Pictographic (hb_codepoint_t cp);
+
+
+#endif /* HB_UNICODE_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-utf-private.hh	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-/*
- * Copyright © 2011,2012,2014  Google, Inc.
- *
- *  This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_UTF_PRIVATE_HH
-#define HB_UTF_PRIVATE_HH
-
-#include "hb-private.hh"
-
-
-struct hb_utf8_t
-{
-  typedef uint8_t codepoint_t;
-
-  static inline const uint8_t *
-  next (const uint8_t *text,
-        const uint8_t *end,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    /* Written to only accept well-formed sequences.
-     * Based on ideas from ICU's U8_NEXT.
-     * Generates one "replacement" for each ill-formed byte. */
-
-    hb_codepoint_t c = *text++;
-
-    if (c > 0x7Fu)
-    {
-      if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */
-      {
-        unsigned int t1;
-        if (likely (text < end &&
-                    (t1 = text[0] - 0x80u) <= 0x3Fu))
-        {
-          c = ((c&0x1Fu)<<6) | t1;
-          text++;
-        }
-        else
-          goto error;
-      }
-      else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */
-      {
-        unsigned int t1, t2;
-        if (likely (1 < end - text &&
-                    (t1 = text[0] - 0x80u) <= 0x3Fu &&
-                    (t2 = text[1] - 0x80u) <= 0x3Fu))
-        {
-          c = ((c&0xFu)<<12) | (t1<<6) | t2;
-          if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-            goto error;
-          text += 2;
-        }
-        else
-          goto error;
-      }
-      else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */
-      {
-        unsigned int t1, t2, t3;
-        if (likely (2 < end - text &&
-                    (t1 = text[0] - 0x80u) <= 0x3Fu &&
-                    (t2 = text[1] - 0x80u) <= 0x3Fu &&
-                    (t3 = text[2] - 0x80u) <= 0x3Fu))
-        {
-          c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
-          if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu)))
-            goto error;
-          text += 3;
-        }
-        else
-          goto error;
-      }
-      else
-        goto error;
-    }
-
-    *unicode = c;
-    return text;
-
-  error:
-    *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint8_t *
-  prev (const uint8_t *text,
-        const uint8_t *start,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    const uint8_t *end = text--;
-    while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
-      text--;
-
-    if (likely (next (text, end, unicode, replacement) == end))
-      return text;
-
-    *unicode = replacement;
-    return end - 1;
-  }
-
-  static inline unsigned int
-  strlen (const uint8_t *text)
-  {
-    return ::strlen ((const char *) text);
-  }
-};
-
-
-struct hb_utf16_t
-{
-  typedef uint16_t codepoint_t;
-
-  static inline const uint16_t *
-  next (const uint16_t *text,
-        const uint16_t *end,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *text++;
-
-    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-    {
-      *unicode = c;
-      return text;
-    }
-
-    if (likely (c <= 0xDBFFu && text < end))
-    {
-      /* High-surrogate in c */
-      hb_codepoint_t l = *text;
-      if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu)))
-      {
-        /* Low-surrogate in l */
-        *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-         text++;
-         return text;
-      }
-    }
-
-    /* Lonely / out-of-order surrogate. */
-    *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint16_t *
-  prev (const uint16_t *text,
-        const uint16_t *start,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *--text;
-
-    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
-    {
-      *unicode = c;
-      return text;
-    }
-
-    if (likely (c >= 0xDC00u && start < text))
-    {
-      /* Low-surrogate in c */
-      hb_codepoint_t h = text[-1];
-      if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
-      {
-        /* High-surrogate in h */
-        *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
-        text--;
-        return text;
-      }
-    }
-
-    /* Lonely / out-of-order surrogate. */
-    *unicode = replacement;
-    return text;
-  }
-
-
-  static inline unsigned int
-  strlen (const uint16_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-
-template <bool validate=true>
-struct hb_utf32_t
-{
-  typedef uint32_t codepoint_t;
-
-  static inline const uint32_t *
-  next (const uint32_t *text,
-        const uint32_t *end HB_UNUSED,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *unicode = *text++;
-    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
-      *unicode = replacement;
-    return text;
-  }
-
-  static inline const uint32_t *
-  prev (const uint32_t *text,
-        const uint32_t *start HB_UNUSED,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    hb_codepoint_t c = *unicode = *--text;
-    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
-      *unicode = replacement;
-    return text;
-  }
-
-  static inline unsigned int
-  strlen (const uint32_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-
-struct hb_latin1_t
-{
-  typedef uint8_t codepoint_t;
-
-  static inline const uint8_t *
-  next (const uint8_t *text,
-        const uint8_t *end HB_UNUSED,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement HB_UNUSED)
-  {
-    *unicode = *text++;
-    return text;
-  }
-
-  static inline const uint8_t *
-  prev (const uint8_t *text,
-        const uint8_t *start HB_UNUSED,
-        hb_codepoint_t *unicode,
-        hb_codepoint_t replacement)
-  {
-    *unicode = *--text;
-    return text;
-  }
-
-  static inline unsigned int
-  strlen (const uint8_t *text)
-  {
-    unsigned int l = 0;
-    while (*text++) l++;
-    return l;
-  }
-};
-
-#endif /* HB_UTF_PRIVATE_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-utf.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,453 @@
+/*
+ * Copyright © 2011,2012,2014  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_UTF_HH
+#define HB_UTF_HH
+
+#include "hb.hh"
+
+#include "hb-open-type.hh"
+
+
+struct hb_utf8_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+        const codepoint_t *end,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    /* Written to only accept well-formed sequences.
+     * Based on ideas from ICU's U8_NEXT.
+     * Generates one "replacement" for each ill-formed byte. */
+
+    hb_codepoint_t c = *text++;
+
+    if (c > 0x7Fu)
+    {
+      if (hb_in_range<hb_codepoint_t> (c, 0xC2u, 0xDFu)) /* Two-byte */
+      {
+        unsigned int t1;
+        if (likely (text < end &&
+                    (t1 = text[0] - 0x80u) <= 0x3Fu))
+        {
+          c = ((c&0x1Fu)<<6) | t1;
+          text++;
+        }
+        else
+          goto error;
+      }
+      else if (hb_in_range<hb_codepoint_t> (c, 0xE0u, 0xEFu)) /* Three-byte */
+      {
+        unsigned int t1, t2;
+        if (likely (1 < end - text &&
+                    (t1 = text[0] - 0x80u) <= 0x3Fu &&
+                    (t2 = text[1] - 0x80u) <= 0x3Fu))
+        {
+          c = ((c&0xFu)<<12) | (t1<<6) | t2;
+          if (unlikely (c < 0x0800u || hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+            goto error;
+          text += 2;
+        }
+        else
+          goto error;
+      }
+      else if (hb_in_range<hb_codepoint_t> (c, 0xF0u, 0xF4u)) /* Four-byte */
+      {
+        unsigned int t1, t2, t3;
+        if (likely (2 < end - text &&
+                    (t1 = text[0] - 0x80u) <= 0x3Fu &&
+                    (t2 = text[1] - 0x80u) <= 0x3Fu &&
+                    (t3 = text[2] - 0x80u) <= 0x3Fu))
+        {
+          c = ((c&0x7u)<<18) | (t1<<12) | (t2<<6) | t3;
+          if (unlikely (!hb_in_range<hb_codepoint_t> (c, 0x10000u, 0x10FFFFu)))
+            goto error;
+          text += 3;
+        }
+        else
+          goto error;
+      }
+      else
+        goto error;
+    }
+
+    *unicode = c;
+    return text;
+
+  error:
+    *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+        const codepoint_t *start,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    const codepoint_t *end = text--;
+    while (start < text && (*text & 0xc0) == 0x80 && end - text < 4)
+      text--;
+
+    if (likely (next (text, end, unicode, replacement) == end))
+      return text;
+
+    *unicode = replacement;
+    return end - 1;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  { return ::strlen ((const char *) text); }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode)
+  {
+    if (unicode <   0x0080u) return 1;
+    if (unicode <   0x0800u) return 2;
+    if (unicode <  0x10000u) return 3;
+    if (unicode < 0x110000u) return 4;
+    return 3;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end,
+          hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    if (unicode < 0x0080u)
+     *text++ = unicode;
+    else if (unicode < 0x0800u)
+    {
+      if (end - text >= 2)
+      {
+        *text++ =  0xC0u + (0x1Fu & (unicode >>  6));
+        *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    else if (unicode < 0x10000u)
+    {
+      if (end - text >= 3)
+      {
+        *text++ =  0xE0u + (0x0Fu & (unicode >> 12));
+        *text++ =  0x80u + (0x3Fu & (unicode >>  6));
+        *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    else
+    {
+      if (end - text >= 4)
+      {
+        *text++ =  0xF0u + (0x07u & (unicode >> 18));
+        *text++ =  0x80u + (0x3Fu & (unicode >> 12));
+        *text++ =  0x80u + (0x3Fu & (unicode >>  6));
+        *text++ =  0x80u + (0x3Fu & (unicode      ));
+      }
+    }
+    return text;
+  }
+};
+
+
+template <typename TCodepoint>
+struct hb_utf16_xe_t
+{
+  static_assert (sizeof (TCodepoint) == 2, "");
+  typedef TCodepoint codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+        const codepoint_t *end,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *text++;
+
+    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+    {
+      *unicode = c;
+      return text;
+    }
+
+    if (likely (c <= 0xDBFFu && text < end))
+    {
+      /* High-surrogate in c */
+      hb_codepoint_t l = *text;
+      if (likely (hb_in_range<hb_codepoint_t> (l, 0xDC00u, 0xDFFFu)))
+      {
+        /* Low-surrogate in l */
+        *unicode = (c << 10) + l - ((0xD800u << 10) - 0x10000u + 0xDC00u);
+         text++;
+         return text;
+      }
+    }
+
+    /* Lonely / out-of-order surrogate. */
+    *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+        const codepoint_t *start,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *--text;
+
+    if (likely (!hb_in_range<hb_codepoint_t> (c, 0xD800u, 0xDFFFu)))
+    {
+      *unicode = c;
+      return text;
+    }
+
+    if (likely (c >= 0xDC00u && start < text))
+    {
+      /* Low-surrogate in c */
+      hb_codepoint_t h = text[-1];
+      if (likely (hb_in_range<hb_codepoint_t> (h, 0xD800u, 0xDBFFu)))
+      {
+        /* High-surrogate in h */
+        *unicode = (h << 10) + c - ((0xD800u << 10) - 0x10000u + 0xDC00u);
+        text--;
+        return text;
+      }
+    }
+
+    /* Lonely / out-of-order surrogate. */
+    *unicode = replacement;
+    return text;
+  }
+
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode)
+  {
+    return unicode < 0x10000 ? 1 : 2;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end,
+          hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    if (unicode < 0x10000u)
+     *text++ = unicode;
+    else if (end - text >= 2)
+    {
+      unicode -= 0x10000u;
+      *text++ =  0xD800u + (unicode >> 10);
+      *text++ =  0xDC00u + (unicode & 0x03FFu);
+    }
+    return text;
+  }
+};
+
+typedef hb_utf16_xe_t<uint16_t> hb_utf16_t;
+typedef hb_utf16_xe_t<OT::HBUINT16> hb_utf16_be_t;
+
+
+template <typename TCodepoint, bool validate=true>
+struct hb_utf32_xe_t
+{
+  static_assert (sizeof (TCodepoint) == 4, "");
+  typedef TCodepoint codepoint_t;
+
+  static const TCodepoint *
+  next (const TCodepoint *text,
+        const TCodepoint *end HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *unicode = *text++;
+    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
+      *unicode = replacement;
+    return text;
+  }
+
+  static const TCodepoint *
+  prev (const TCodepoint *text,
+        const TCodepoint *start HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    hb_codepoint_t c = *unicode = *--text;
+    if (validate && unlikely (c >= 0xD800u && (c <= 0xDFFFu || c > 0x10FFFFu)))
+      *unicode = replacement;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const TCodepoint *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end HB_UNUSED,
+          hb_codepoint_t unicode)
+  {
+    if (validate && unlikely (unicode >= 0xD800u && (unicode <= 0xDFFFu || unicode > 0x10FFFFu)))
+      unicode = 0xFFFDu;
+    *text++ = unicode;
+    return text;
+  }
+};
+
+typedef hb_utf32_xe_t<uint32_t> hb_utf32_t;
+typedef hb_utf32_xe_t<uint32_t, false> hb_utf32_novalidate_t;
+
+
+struct hb_latin1_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+        const codepoint_t *end HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *text++;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+        const codepoint_t *start HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *--text;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end HB_UNUSED,
+          hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0x0100u))
+      unicode = '?';
+    *text++ = unicode;
+    return text;
+  }
+};
+
+
+struct hb_ascii_t
+{
+  typedef uint8_t codepoint_t;
+
+  static const codepoint_t *
+  next (const codepoint_t *text,
+        const codepoint_t *end HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement HB_UNUSED)
+  {
+    *unicode = *text++;
+    if (*unicode >= 0x0080u)
+      *unicode = replacement;
+    return text;
+  }
+
+  static const codepoint_t *
+  prev (const codepoint_t *text,
+        const codepoint_t *start HB_UNUSED,
+        hb_codepoint_t *unicode,
+        hb_codepoint_t replacement)
+  {
+    *unicode = *--text;
+    if (*unicode >= 0x0080u)
+      *unicode = replacement;
+    return text;
+  }
+
+  static unsigned int
+  strlen (const codepoint_t *text)
+  {
+    unsigned int l = 0;
+    while (*text++) l++;
+    return l;
+  }
+
+  static unsigned int
+  encode_len (hb_codepoint_t unicode HB_UNUSED)
+  {
+    return 1;
+  }
+
+  static codepoint_t *
+  encode (codepoint_t *text,
+          const codepoint_t *end HB_UNUSED,
+          hb_codepoint_t unicode)
+  {
+    if (unlikely (unicode >= 0x0080u))
+      unicode = '?';
+    *text++ = unicode;
+    return text;
+  }
+};
+
+#endif /* HB_UTF_HH */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-vector.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,260 @@
+/*
+ * Copyright © 2017,2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_VECTOR_HH
+#define HB_VECTOR_HH
+
+#include "hb.hh"
+#include "hb-array.hh"
+#include "hb-null.hh"
+
+
+template <typename Type>
+struct hb_vector_t
+{
+  typedef Type item_t;
+  static constexpr unsigned item_size = hb_static_size (Type);
+
+  HB_NO_COPY_ASSIGN_TEMPLATE (hb_vector_t, Type);
+  hb_vector_t ()  { init (); }
+  ~hb_vector_t () { fini (); }
+
+  unsigned int length;
+  private:
+  int allocated; /* == -1 means allocation failed. */
+  Type *arrayZ_;
+  public:
+
+  void init ()
+  {
+    allocated = length = 0;
+    arrayZ_ = nullptr;
+  }
+
+  void fini ()
+  {
+    if (arrayZ_)
+      free (arrayZ_);
+    init ();
+  }
+  void fini_deep ()
+  {
+    Type *array = arrayZ();
+    unsigned int count = length;
+    for (unsigned int i = 0; i < count; i++)
+      array[i].fini ();
+    fini ();
+  }
+
+  const Type * arrayZ () const { return arrayZ_; }
+        Type * arrayZ ()       { return arrayZ_; }
+
+  Type& operator [] (int i_)
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= length))
+      return Crap (Type);
+    return arrayZ()[i];
+  }
+  const Type& operator [] (int i_) const
+  {
+    unsigned int i = (unsigned int) i_;
+    if (unlikely (i >= length))
+      return Null(Type);
+    return arrayZ()[i];
+  }
+
+  explicit_operator bool () const { return length; }
+
+  hb_array_t<Type> as_array ()
+  { return hb_array (arrayZ(), length); }
+  hb_array_t<const Type> as_array () const
+  { return hb_array (arrayZ(), length); }
+
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
+  { return as_array ().sub_array (start_offset, count);}
+  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_array ().sub_array (start_offset, count);}
+
+  hb_sorted_array_t<Type> as_sorted_array ()
+  { return hb_sorted_array (arrayZ(), length); }
+  hb_sorted_array_t<const Type> as_sorted_array () const
+  { return hb_sorted_array (arrayZ(), length); }
+
+  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int count) const
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int count)
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
+  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
+
+  template <typename T> explicit_operator T * () { return arrayZ(); }
+  template <typename T> explicit_operator const T * () const { return arrayZ(); }
+  operator hb_array_t<Type> ()             { return as_array (); }
+  operator hb_array_t<const Type> () const { return as_array (); }
+
+  Type * operator  + (unsigned int i) { return arrayZ() + i; }
+  const Type * operator  + (unsigned int i) const { return arrayZ() + i; }
+
+  Type *push ()
+  {
+    if (unlikely (!resize (length + 1)))
+      return &Crap(Type);
+    return &arrayZ()[length - 1];
+  }
+  Type *push (const Type& v)
+  {
+    Type *p = push ();
+    *p = v;
+    return p;
+  }
+
+  bool in_error () const { return allocated < 0; }
+
+  /* Allocate for size but don't adjust length. */
+  bool alloc (unsigned int size)
+  {
+    if (unlikely (allocated < 0))
+      return false;
+
+    if (likely (size <= (unsigned) allocated))
+      return true;
+
+    /* Reallocate */
+
+    unsigned int new_allocated = allocated;
+    while (size >= new_allocated)
+      new_allocated += (new_allocated >> 1) + 8;
+
+    Type *new_array = nullptr;
+    bool overflows =
+      (int) new_allocated < 0 ||
+      (new_allocated < (unsigned) allocated) ||
+      hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
+    if (likely (!overflows))
+      new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type));
+
+    if (unlikely (!new_array))
+    {
+      allocated = -1;
+      return false;
+    }
+
+    arrayZ_ = new_array;
+    allocated = new_allocated;
+
+    return true;
+  }
+
+  bool resize (int size_)
+  {
+    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+    if (!alloc (size))
+      return false;
+
+    if (size > length)
+      memset (arrayZ() + length, 0, (size - length) * sizeof (*arrayZ()));
+
+    length = size;
+    return true;
+  }
+
+  void pop ()
+  {
+    if (!length) return;
+    length--;
+  }
+
+  void remove (unsigned int i)
+  {
+    if (unlikely (i >= length))
+      return;
+    Type *array = arrayZ();
+    memmove (static_cast<void *> (&array[i]),
+             static_cast<void *> (&array[i + 1]),
+             (length - i - 1) * sizeof (Type));
+    length--;
+  }
+
+  void shrink (int size_)
+  {
+    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+     if (size < length)
+       length = size;
+  }
+
+  template <typename T>
+  Type *find (T v)
+  {
+    Type *array = arrayZ();
+    for (unsigned int i = 0; i < length; i++)
+      if (array[i] == v)
+        return &array[i];
+    return nullptr;
+  }
+  template <typename T>
+  const Type *find (T v) const
+  {
+    const Type *array = arrayZ();
+    for (unsigned int i = 0; i < length; i++)
+      if (array[i] == v)
+        return &array[i];
+    return nullptr;
+  }
+
+  void qsort (int (*cmp)(const void*, const void*))
+  { as_array ().qsort (cmp); }
+  void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
+  { as_array ().qsort (start, end); }
+
+  template <typename T>
+  Type *lsearch (const T &x, Type *not_found = nullptr)
+  { return as_array ().lsearch (x, not_found); }
+  template <typename T>
+  const Type *lsearch (const T &x, const Type *not_found = nullptr) const
+  { return as_array ().lsearch (x, not_found); }
+
+  template <typename T>
+  Type *bsearch (const T &x, Type *not_found = nullptr)
+  { return as_sorted_array ().bsearch (x, not_found); }
+  template <typename T>
+  const Type *bsearch (const T &x, const Type *not_found = nullptr) const
+  { return as_sorted_array ().bsearch (x, not_found); }
+  template <typename T>
+  bool bfind (const T &x, unsigned int *i = nullptr,
+                     hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
+                     unsigned int to_store = (unsigned int) -1) const
+  { return as_sorted_array ().bfind (x, i, not_found, to_store); }
+};
+
+
+#endif /* HB_VECTOR_HH */
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-version.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-version.h	Tue Mar 26 09:05:10 2019 -0400
@@ -36,11 +36,11 @@
 HB_BEGIN_DECLS
 
 
-#define HB_VERSION_MAJOR 1
-#define HB_VERSION_MINOR 8
-#define HB_VERSION_MICRO 2
+#define HB_VERSION_MAJOR 2
+#define HB_VERSION_MINOR 3
+#define HB_VERSION_MICRO 1
 
-#define HB_VERSION_STRING "1.8.2"
+#define HB_VERSION_STRING "2.3.1"
 
 #define HB_VERSION_ATLEAST(major,minor,micro) \
         ((major)*10000+(minor)*100+(micro) <= \
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-warning.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-warning.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -24,16 +24,14 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#include "hb-atomic-private.hh"
-#include "hb-mutex-private.hh"
-
+#include "hb.hh"
 
 #if defined(HB_ATOMIC_INT_NIL)
 #error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe"
-#error "Check hb-atomic-private.hh for possible resolutions."
+#error "Check hb-atomic.hh for possible resolutions."
 #endif
 
 #if defined(HB_MUTEX_IMPL_NIL)
 #error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
-#error "Check hb-mutex-private.hh for possible resolutions."
+#error "Check hb-mutex.hh for possible resolutions."
 #endif
--- a/src/java.desktop/share/native/libfontmanager/harfbuzz/hb.h	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb.h	Tue Mar 26 09:05:10 2019 -0400
@@ -28,10 +28,6 @@
 #define HB_H
 #define HB_H_IN
 
-#ifndef HB_EXTERN
-#define HB_EXTERN extern
-#endif
-
 #include "hb-blob.h"
 #include "hb-buffer.h"
 #include "hb-common.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/share/native/libfontmanager/harfbuzz/hb.hh	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,658 @@
+/*
+ * Copyright © 2007,2008,2009  Red Hat, Inc.
+ * Copyright © 2011,2012  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_HH
+#define HB_HH
+
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
+#if defined(_MSC_VER)
+#pragma warning( disable: 4068 ) /* Unknown pragma */
+#endif
+#if defined(__GNUC__) || defined(__clang__)
+/* Rules:
+ *
+ * - All pragmas are declared GCC even if they are clang ones.  Otherwise GCC
+ *   nags, even though we instruct it to ignore -Wunknown-pragmas. ¯\_(ツ)_/¯
+ *
+ * - Within each category, keep sorted.
+ *
+ * - Warnings whose scope can be expanded in future compiler versions shall
+ *   be declared as "warning".  Otherwise, either ignored or error.
+ */
+
+/* Setup.  Don't sort order within this category. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+#pragma GCC diagnostic warning "-Wall"
+#pragma GCC diagnostic warning "-Wextra"
+#endif
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#pragma GCC diagnostic ignored "-Wunknown-warning-option"
+#endif
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+//#pragma GCC diagnostic warning "-Weverything"
+#endif
+
+/* Error.  Should never happen. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
+#pragma GCC diagnostic error   "-Wc++11-narrowing"
+#pragma GCC diagnostic error   "-Wcast-align"
+#pragma GCC diagnostic error   "-Wcast-function-type"
+#pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
+#pragma GCC diagnostic error   "-Wformat-security"
+#pragma GCC diagnostic error   "-Wimplicit-function-declaration"
+#pragma GCC diagnostic error   "-Winit-self"
+#pragma GCC diagnostic error   "-Wmissing-braces"
+#pragma GCC diagnostic error   "-Wmissing-declarations"
+#pragma GCC diagnostic error   "-Wmissing-prototypes"
+#pragma GCC diagnostic error   "-Wnested-externs"
+#pragma GCC diagnostic error   "-Wold-style-definition"
+#pragma GCC diagnostic error   "-Wpointer-arith"
+#pragma GCC diagnostic error   "-Wredundant-decls"
+#pragma GCC diagnostic error   "-Wreorder"
+#pragma GCC diagnostic error   "-Wsign-compare"
+#pragma GCC diagnostic error   "-Wstrict-prototypes"
+#pragma GCC diagnostic error   "-Wstring-conversion"
+#pragma GCC diagnostic error   "-Wswitch-enum"
+#pragma GCC diagnostic error   "-Wtautological-overlap-compare"
+#pragma GCC diagnostic error   "-Wunneeded-internal-declaration"
+#pragma GCC diagnostic error   "-Wunused"
+#pragma GCC diagnostic error   "-Wunused-local-typedefs"
+#pragma GCC diagnostic error   "-Wunused-value"
+#pragma GCC diagnostic error   "-Wunused-variable"
+#pragma GCC diagnostic error   "-Wvla"
+#pragma GCC diagnostic error   "-Wwrite-strings"
+#endif
+
+/* Warning.  To be investigated if happens. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
+#pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
+#pragma GCC diagnostic warning "-Wdisabled-optimization"
+#pragma GCC diagnostic warning "-Wformat=2"
+#pragma GCC diagnostic warning "-Wignored-pragma-optimize"
+#pragma GCC diagnostic warning "-Wlogical-op"
+#pragma GCC diagnostic warning "-Wmaybe-uninitialized"
+#pragma GCC diagnostic warning "-Wmissing-format-attribute"
+#pragma GCC diagnostic warning "-Wundef"
+#endif
+
+/* Ignored currently, but should be fixed at some point. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wconversion"                   // TODO fix
+#pragma GCC diagnostic ignored "-Wformat-signedness"            // TODO fix
+#pragma GCC diagnostic ignored "-Wshadow"                       // TODO fix
+#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"    // TODO fix
+#pragma GCC diagnostic ignored "-Wunused-parameter"             // TODO fix
+#endif
+
+/* Ignored intentionally. */
+#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#pragma GCC diagnostic ignored "-Wformat-zero-length"
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
+
+#endif
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Following added based on what AC_USE_SYSTEM_EXTENSIONS adds to
+ * config.h.in.  Copied here for the convenience of those embedding
+ * HarfBuzz and not using our build system.
+ */
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# define _ALL_SOURCE 1
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# define _TANDEM_SOURCE 1
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__ 1
+#endif
+
+#if defined (_MSC_VER) && defined (HB_DLL_EXPORT)
+#define HB_EXTERN __declspec (dllexport) extern
+#endif
+
+#include "hb.h"
+#define HB_H_IN
+#include "hb-ot.h"
+#define HB_OT_H_IN
+#include "hb-aat.h"
+#define HB_AAT_H_IN
+
+#include "hb-aat.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
+#include <intrin.h>
+#endif
+
+#define HB_PASTE1(a,b) a##b
+#define HB_PASTE(a,b) HB_PASTE1(a,b)
+
+
+/* Compile-time custom allocator support. */
+
+#if defined(hb_malloc_impl) \
+ && defined(hb_calloc_impl) \
+ && defined(hb_realloc_impl) \
+ && defined(hb_free_impl)
+extern "C" void* hb_malloc_impl(size_t size);
+extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
+extern "C" void* hb_realloc_impl(void *ptr, size_t size);
+extern "C" void  hb_free_impl(void *ptr);
+#define malloc hb_malloc_impl
+#define calloc hb_calloc_impl
+#define realloc hb_realloc_impl
+#define free hb_free_impl
+
+#if defined(hb_memalign_impl)
+extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
+#define posix_memalign hb_memalign_impl
+#else
+#undef HAVE_POSIX_MEMALIGN
+#endif
+
+#endif
+
+
+/*
+ * Compiler attributes
+ */
+
+#if __cplusplus < 201103L
+
+#ifndef nullptr
+#define nullptr NULL
+#endif
+
+#ifndef constexpr
+#define constexpr const
+#endif
+
+#ifndef static_assert
+#define static_assert(e, msg) \
+        HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
+#endif // static_assert
+
+#if defined(__GNUC__)
+#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
+#define thread_local __thread
+#endif
+#else
+#define thread_local
+#endif
+
+template <typename T>
+struct _hb_alignof
+{
+  struct s
+  {
+    char c;
+    T t;
+  };
+  static constexpr size_t value = offsetof (s, t);
+};
+#ifndef alignof
+#define alignof(x) (_hb_alignof<x>::value)
+#endif
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
+#ifndef explicit_operator
+#define explicit_operator operator
+#endif
+
+#else /* __cplusplus >= 201103L */
+
+/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
+#ifndef explicit_operator
+#define explicit_operator explicit operator
+#endif
+
+#endif /* __cplusplus < 201103L */
+
+
+#if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
+#define likely(expr) (__builtin_expect (!!(expr), 1))
+#define unlikely(expr) (__builtin_expect (!!(expr), 0))
+#else
+#define likely(expr) (expr)
+#define unlikely(expr) (expr)
+#endif
+
+#if !defined(__GNUC__) && !defined(__clang__)
+#undef __attribute__
+#define __attribute__(x)
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define HB_PURE_FUNC    __attribute__((pure))
+#define HB_CONST_FUNC   __attribute__((const))
+#define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#else
+#define HB_PURE_FUNC
+#define HB_CONST_FUNC
+#define HB_PRINTF_FUNC(format_idx, arg_idx)
+#endif
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define HB_UNUSED       __attribute__((unused))
+#elif defined(_MSC_VER) /* https://github.com/harfbuzz/harfbuzz/issues/635 */
+#define HB_UNUSED __pragma(warning(suppress: 4100 4101))
+#else
+#define HB_UNUSED
+#endif
+
+#ifndef HB_INTERNAL
+# if !defined(HB_NO_VISIBILITY) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_MSC_VER) && !defined(__SUNPRO_CC)
+#  define HB_INTERNAL __attribute__((__visibility__("hidden")))
+# elif defined(__MINGW32__)
+   /* We use -export-symbols on mingw32, since it does not support visibility attributes. */
+#  define HB_INTERNAL
+# elif defined (_MSC_VER) && defined (HB_DLL_EXPORT)
+   /* We do not try to export internal symbols on Visual Studio */
+#  define HB_INTERNAL
+#else
+#  define HB_INTERNAL
+#  define HB_NO_VISIBILITY 1
+# endif
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define HB_FUNC __PRETTY_FUNCTION__
+#elif defined(_MSC_VER)
+#define HB_FUNC __FUNCSIG__
+#else
+#define HB_FUNC __func__
+#endif
+
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5140)
+/* https://github.com/harfbuzz/harfbuzz/issues/630 */
+#define __restrict
+#endif
+
+/*
+ * Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
+ * HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
+ * cases that fall through without a break or return statement. HB_FALLTHROUGH
+ * is only needed on cases that have code:
+ *
+ * switch (foo) {
+ *   case 1: // These cases have no code. No fallthrough annotations are needed.
+ *   case 2:
+ *   case 3:
+ *     foo = 4; // This case has code, so a fallthrough annotation is needed:
+ *     HB_FALLTHROUGH;
+ *   default:
+ *     return foo;
+ * }
+ */
+#if defined(__clang__) && __cplusplus >= 201103L
+   /* clang's fallthrough annotations are only available starting in C++11. */
+#  define HB_FALLTHROUGH [[clang::fallthrough]]
+#elif defined(__GNUC__) && (__GNUC__ >= 7)
+   /* GNU fallthrough attribute is available from GCC7 */
+#  define HB_FALLTHROUGH __attribute__((fallthrough))
+#elif defined(_MSC_VER)
+   /*
+    * MSVC's __fallthrough annotations are checked by /analyze (Code Analysis):
+    * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
+    */
+#  include <sal.h>
+#  define HB_FALLTHROUGH __fallthrough
+#else
+#  define HB_FALLTHROUGH /* FALLTHROUGH */
+#endif
+
+#if defined(__clang__)
+/* Disable certain sanitizer errors. */
+/* https://github.com/harfbuzz/harfbuzz/issues/1247 */
+#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow")))
+#else
+#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW
+#endif
+
+
+#ifdef _WIN32
+   /* We need Windows Vista for both Uniscribe backend and for
+    * MemoryBarrier.  We don't support compiling on Windows XP,
+    * though we run on it fine. */
+#  if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0600
+#    undef _WIN32_WINNT
+#  endif
+#  ifndef _WIN32_WINNT
+#    if !defined(WINAPI_FAMILY) || !(WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#      define _WIN32_WINNT 0x0600
+#    endif
+#  endif
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN 1
+#  endif
+#  ifndef STRICT
+#    define STRICT 1
+#  endif
+
+#  if defined(_WIN32_WCE)
+     /* Some things not defined on Windows CE. */
+#    define vsnprintf _vsnprintf
+#    define getenv(Name) nullptr
+#    if _WIN32_WCE < 0x800
+#      define setlocale(Category, Locale) "C"
+static int errno = 0; /* Use something better? */
+#    endif
+#  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
+#    define getenv(Name) nullptr
+#  endif
+#  if defined(_MSC_VER) && _MSC_VER < 1900
+#    define snprintf _snprintf
+#  endif
+#endif
+
+#if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
+/* atexit() is only safe to be called from shared libraries on certain
+ * platforms.  Whitelist.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
+#  if defined(__linux) && defined(__GLIBC_PREREQ)
+#    if __GLIBC_PREREQ(2,3)
+/* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
+#      define HB_USE_ATEXIT 1
+#    endif
+#  elif defined(_MSC_VER) || defined(__MINGW32__)
+/* For MSVC:
+ * https://msdn.microsoft.com/en-us/library/tze57ck3.aspx
+ * https://msdn.microsoft.com/en-us/library/zk17ww08.aspx
+ * mingw32 headers say atexit is safe to use in shared libraries.
+ */
+#    define HB_USE_ATEXIT 1
+#  elif defined(__ANDROID__)
+/* This is available since Android NKD r8 or r8b:
+ * https://issuetracker.google.com/code/p/android/issues/detail?id=6455
+ */
+#    define HB_USE_ATEXIT 1
+#  elif defined(__APPLE__)
+/* For macOS and related platforms, the atexit man page indicates
+ * that it will be invoked when the library is unloaded, not only
+ * at application exit.
+ */
+#    define HB_USE_ATEXIT 1
+#  endif
+#endif
+#ifdef HB_NO_ATEXIT
+#  undef HB_USE_ATEXIT
+#endif
+#ifndef HB_USE_ATEXIT
+#  define HB_USE_ATEXIT 0
+#endif
+
+#define HB_STMT_START do
+#define HB_STMT_END   while (0)
+
+/* Static-assert as expression. */
+template <unsigned int cond> class hb_assert_constant_t;
+template <> class hb_assert_constant_t<1> {};
+#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
+
+/* Lets assert int types.  Saves trouble down the road. */
+static_assert ((sizeof (int8_t) == 1), "");
+static_assert ((sizeof (uint8_t) == 1), "");
+static_assert ((sizeof (int16_t) == 2), "");
+static_assert ((sizeof (uint16_t) == 2), "");
+static_assert ((sizeof (int32_t) == 4), "");
+static_assert ((sizeof (uint32_t) == 4), "");
+static_assert ((sizeof (int64_t) == 8), "");
+static_assert ((sizeof (uint64_t) == 8), "");
+static_assert ((sizeof (hb_codepoint_t) == 4), "");
+static_assert ((sizeof (hb_position_t) == 4), "");
+static_assert ((sizeof (hb_mask_t) == 4), "");
+static_assert ((sizeof (hb_var_int_t) == 4), "");
+
+
+#if __cplusplus >= 201103L
+
+/* We only enable these with C++11 or later, since earlier language
+ * does not allow structs with constructors in unions, and we need
+ * those. */
+
+#define HB_NO_COPY_ASSIGN(TypeName) \
+  TypeName(const TypeName&); \
+  void operator=(const TypeName&)
+#define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) \
+  TypeName(const TypeName<T>&); \
+  void operator=(const TypeName<T>&)
+#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \
+  TypeName(const TypeName<T1, T2>&); \
+  void operator=(const TypeName<T1, T2>&)
+#define HB_NO_CREATE_COPY_ASSIGN(TypeName) \
+  TypeName(); \
+  TypeName(const TypeName&); \
+  void operator=(const TypeName&)
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) \
+  TypeName(); \
+  TypeName(const TypeName<T>&); \
+  void operator=(const TypeName<T>&)
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \
+  TypeName(); \
+  TypeName(const TypeName<T1, T2>&); \
+  void operator=(const TypeName<T1, T2>&)
+
+#else /* __cpluspplus >= 201103L */
+
+#define HB_NO_COPY_ASSIGN(TypeName) static_assert (true, "")
+#define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "")
+#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN(TypeName) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "")
+#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "")
+
+#endif /* __cpluspplus >= 201103L */
+
+
+/*
+ * Compiler-assisted vectorization parameters.
+ */
+
+/*
+ * Disable vectorization for now.  To correctly use them, we should
+ * use posix_memalign() to allocate in hb_vector_t.  Otherwise, can
+ * cause misaligned access.
+ *
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
+ */
+#if !defined(HB_VECTOR_SIZE)
+#  define HB_VECTOR_SIZE 0
+#endif
+
+/* The `vector_size' attribute was introduced in gcc 3.1. */
+#if !defined(HB_VECTOR_SIZE)
+#  if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
+#    define HB_VECTOR_SIZE 128
+#  else
+#    define HB_VECTOR_SIZE 0
+#  endif
+#endif
+static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2.");
+static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64.");
+#if HB_VECTOR_SIZE
+typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
+#else
+typedef uint64_t hb_vector_size_impl_t;
+#endif
+
+
+/* HB_NDEBUG disables some sanity checks that are very safe to disable and
+ * should be disabled in production systems.  If NDEBUG is defined, enable
+ * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
+ * light-weight) to be enabled, then HB_DEBUG can be defined to disable
+ * the costlier checks. */
+#ifdef NDEBUG
+#define HB_NDEBUG 1
+#endif
+
+
+/* Flags */
+
+/* Enable bitwise ops on enums marked as flags_t */
+/* To my surprise, looks like the function resolver is happy to silently cast
+ * one enum to another...  So this doesn't provide the type-checking that I
+ * originally had in mind... :(.
+ *
+ * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
+ */
+#ifdef _MSC_VER
+# pragma warning(disable:4200)
+# pragma warning(disable:4800)
+#endif
+#define HB_MARK_AS_FLAG_T(T) \
+        extern "C++" { \
+          static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
+          static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
+          static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
+          static inline T operator ~ (T r) { return T (~(unsigned int) r); } \
+          static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
+          static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
+          static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
+        } \
+        static_assert (true, "")
+
+/* Useful for set-operations on small enums.
+ * For example, for testing "x ∈ {x1, x2, x3}" use:
+ * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
+ */
+#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x)))
+#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0)
+#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x))
+#define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
+#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
+
+
+/* Size signifying variable-sized array */
+#define VAR 1
+
+
+/* fallback for round() */
+static inline double
+_hb_round (double x)
+{
+  if (x >= 0)
+    return floor (x + 0.5);
+  else
+    return ceil (x - 0.5);
+}
+#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
+#define round(x) _hb_round(x)
+#endif
+
+
+/* fallback for posix_memalign() */
+static inline int
+_hb_memalign(void **memptr, size_t alignment, size_t size)
+{
+  if (unlikely (0 != (alignment & (alignment - 1)) ||
+                !alignment ||
+                0 != (alignment & (sizeof (void *) - 1))))
+    return EINVAL;
+
+  char *p = (char *) malloc (size + alignment - 1);
+  if (unlikely (!p))
+    return ENOMEM;
+
+  size_t off = (size_t) p & (alignment - 1);
+  if (off)
+    p += alignment - off;
+
+  *memptr = (void *) p;
+
+  return 0;
+}
+#if !defined(posix_memalign) && !defined(HAVE_POSIX_MEMALIGN)
+#define posix_memalign _hb_memalign
+#endif
+
+
+/*
+ * For lack of a better place, put Zawgyi script hack here.
+ * https://github.com/harfbuzz/harfbuzz/issues/1162
+ */
+
+#define HB_SCRIPT_MYANMAR_ZAWGYI        ((hb_script_t) HB_TAG ('Q','a','a','g'))
+
+
+/* Some really basic things everyone wants. */
+template <typename T> struct hb_remove_const { typedef T value; };
+template <typename T> struct hb_remove_const<const T> { typedef T value; };
+#define hb_remove_const(T) hb_remove_const<T>::value
+template <typename T> struct hb_remove_reference { typedef T value; };
+template <typename T> struct hb_remove_reference<T &> { typedef T value; };
+#define hb_remove_reference(T) hb_remove_reference<T>::value
+template <typename T> struct hb_remove_pointer { typedef T value; };
+template <typename T> struct hb_remove_pointer<T *> { typedef T value; };
+#define hb_remove_pointer(T) hb_remove_pointer<T>::value
+
+
+/* Headers we include for everyone.  Keep topologically sorted by dependency.
+ * They express dependency amongst themselves, but no other file should include
+ * them directly.*/
+#include "hb-atomic.hh"
+#include "hb-mutex.hh"
+#include "hb-null.hh"
+#include "hb-dsalgs.hh" // Requires: hb-null
+#include "hb-iter.hh"   // Requires: hb-null
+#include "hb-debug.hh"  // Requires: hb-atomic hb-dsalgs
+#include "hb-array.hh"  // Requires: hb-dsalgs hb-iter hb-null
+#include "hb-vector.hh" // Requires: hb-array hb-null
+#include "hb-object.hh" // Requires: hb-atomic hb-mutex hb-vector
+
+#endif /* HB_HH */
--- a/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc	Tue Mar 26 09:05:10 2019 -0400
@@ -36,8 +36,32 @@
 #define HB_UNUSED
 #endif
 
+
 static hb_bool_t
-hb_jdk_get_glyph (hb_font_t *font HB_UNUSED,
+hb_jdk_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+		          void *font_data,
+		          hb_codepoint_t unicode,
+		          hb_codepoint_t *glyph,
+		          void *user_data HB_UNUSED)
+{
+
+    JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data;
+    JNIEnv* env = jdkFontInfo->env;
+    jobject font2D = jdkFontInfo->font2D;
+    *glyph = (hb_codepoint_t)env->CallIntMethod(
+              font2D, sunFontIDs.f2dCharToGlyphMID, unicode);
+    if (env->ExceptionOccurred())
+    {
+        env->ExceptionClear();
+    }
+    if ((int)*glyph < 0) {
+        *glyph = 0;
+    }
+    return (*glyph != 0);
+}
+
+static hb_bool_t
+hb_jdk_get_variation_glyph (hb_font_t *font HB_UNUSED,
 		 void *font_data,
 		 hb_codepoint_t unicode,
 		 hb_codepoint_t variation_selector,
@@ -48,14 +72,9 @@
     JDKFontInfo *jdkFontInfo = (JDKFontInfo*)font_data;
     JNIEnv* env = jdkFontInfo->env;
     jobject font2D = jdkFontInfo->font2D;
-    if (variation_selector == 0) {
-        *glyph = (hb_codepoint_t)env->CallIntMethod(
-                     font2D, sunFontIDs.f2dCharToGlyphMID, unicode);
-    } else {
-        *glyph = (hb_codepoint_t)env->CallIntMethod(
-                     font2D, sunFontIDs.f2dCharToVariationGlyphMID, 
-                     unicode, variation_selector);
-    }
+    *glyph = (hb_codepoint_t)env->CallIntMethod(
+              font2D, sunFontIDs.f2dCharToVariationGlyphMID, 
+              unicode, variation_selector);
     if (env->ExceptionOccurred())
     {
         env->ExceptionClear();
@@ -251,7 +270,8 @@
   if (!jdk_ffuncs) {
       ff = hb_font_funcs_create();
 
-      hb_font_funcs_set_glyph_func(ff, hb_jdk_get_glyph, NULL, NULL);
+      hb_font_funcs_set_nominal_glyph_func(ff, hb_jdk_get_nominal_glyph, NULL, NULL);
+      hb_font_funcs_set_variation_glyph_func(ff, hb_jdk_get_variation_glyph, NULL, NULL);
       hb_font_funcs_set_glyph_h_advance_func(ff,
                     hb_jdk_get_glyph_h_advance, NULL, NULL);
       hb_font_funcs_set_glyph_v_advance_func(ff,
--- a/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java	Tue Mar 26 09:05:10 2019 -0400
@@ -449,14 +449,7 @@
             if (!doEraseBackground()) {
                 return;
             }
-            // 6304250: XAWT: Items in choice show a blue border on OpenGL + Solaris10 when background color is set
-            // Note: When OGL is enabled, surfaceData.pixelFor() will not
-            // return a pixel value appropriate for passing to
-            // XSetWindowBackground().  Therefore, we will use the ColorModel
-            // for this component in order to calculate a pixel value from
-            // the given RGB value.
-            ColorModel cm = getColorModel();
-            int pixel = PixelConverter.instance.rgbToPixel(c.getRGB(), cm);
+            int pixel = surfaceData.pixelFor(c.getRGB());
             XlibWrapper.XSetWindowBackground(XToolkit.getDisplay(), getContentWindow(), pixel);
             XlibWrapper.XClearWindow(XToolkit.getDisplay(), getContentWindow());
         }
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1777,13 +1777,9 @@
         (widget_type == CHECK_BOX || widget_type == RADIO_BUTTON)) {
         return;
     }
-    gtk3_widget = gtk3_get_widget(widget_type);
-
-    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
-    fp_gtk_style_context_save (context);
-
-    if (detail != 0) {
-        transform_detail_string(detail, context);
+    GtkStyleContext* context = get_style(widget_type, detail);
+    if (widget_type == TOOL_TIP) {
+        fp_gtk_style_context_add_class(context, "background");
     }
 
     GtkStateFlags flags = get_gtk_flags(state_type);
@@ -1800,7 +1796,7 @@
 
     fp_gtk_render_background (context, cr, x, y, width, height);
 
-    fp_gtk_style_context_restore (context);
+    disposeOrRestoreContext(context);
 }
 
 static void gtk3_paint_focus(WidgetType widget_type, GtkStateType state_type,
@@ -2360,17 +2356,19 @@
 
     init_containers();
 
-    if (widget_type == TEXT_FIELD && state_type == GTK_STATE_SELECTED &&
-        color_type == TEXT_BACKGROUND) {
-        widget_type = TEXT_AREA;
+    if (gtk3_version_3_20) {
+        if ((widget_type == TEXT_FIELD || widget_type == PASSWORD_FIELD || widget_type == SPINNER_TEXT_FIELD ||
+            widget_type == FORMATTED_TEXT_FIELD) && state_type == GTK_STATE_SELECTED && color_type == TEXT_BACKGROUND) {
+            widget_type = TEXT_AREA;
+        }
     }
 
-    gtk3_widget = gtk3_get_widget(widget_type);
-
-    GtkStyleContext* context = fp_gtk_widget_get_style_context(gtk3_widget);
-
+    GtkStyleContext* context = NULL;
     if (widget_type == TOOL_TIP) {
-        fp_gtk_style_context_add_class(context, "tooltip");
+        context = get_style(widget_type, "tooltip");
+    } else {
+        gtk3_widget = gtk3_get_widget(widget_type);
+        context = fp_gtk_widget_get_style_context(gtk3_widget);
     }
     if (widget_type == CHECK_BOX_MENU_ITEM
      || widget_type == RADIO_BUTTON_MENU_ITEM) {
@@ -2388,7 +2386,9 @@
 
     result = recode_color(color.alpha) << 24 | recode_color(color.red) << 16 |
              recode_color(color.green) << 8 | recode_color(color.blue);
-
+    if (widget_type == TOOL_TIP) {
+        disposeOrRestoreContext(context);
+    }
     return result;
 }
 
--- a/src/java.desktop/windows/native/libfontmanager/fontpath.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.desktop/windows/native/libfontmanager/fontpath.c	Tue Mar 26 09:05:10 2019 -0400
@@ -511,14 +511,9 @@
     DeleteLocalReference(env, fileStr);
 }
 
-/* Obtain all the fontname -> filename mappings.
- * This is called once and the results returned to Java code which can
- * use it for lookups to reduce or avoid the need to search font files.
- */
-JNIEXPORT void JNICALL
-Java_sun_awt_Win32FontManager_populateFontFileNameMap0
-(JNIEnv *env, jclass obj, jobject fontToFileMap,
- jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale)
+static void populateFontFileNameFromRegistryKey(HKEY regKey,
+                                                GdiFontMapInfo *fmi,
+                                                jobject fontToFileMap)
 {
 #define MAX_BUFFER (FILENAME_MAX+1)
     const wchar_t wname[MAX_BUFFER];
@@ -531,7 +526,63 @@
     DWORD dwDataValueSize;
     DWORD nval;
     DWORD dwNumValues, dwMaxValueNameLen, dwMaxValueDataLen;
-    DWORD numValues = 0;
+
+    /* Use the windows registry to map font names to files */
+    ret = RegOpenKeyEx(regKey,
+                       FONTKEY_NT, 0L, KEY_READ, &hkeyFonts);
+    if (ret != ERROR_SUCCESS) {
+        return;
+    }
+
+    ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
+                           &dwNumValues, &dwMaxValueNameLen,
+                           &dwMaxValueDataLen, NULL, NULL);
+
+    if (ret != ERROR_SUCCESS ||
+        dwMaxValueNameLen >= MAX_BUFFER ||
+        dwMaxValueDataLen >= MAX_BUFFER) {
+        RegCloseKey(hkeyFonts);
+        return;
+    }
+    for (nval = 0; nval < dwNumValues; nval++ ) {
+        dwNameSize = MAX_BUFFER;
+        dwDataValueSize = MAX_BUFFER;
+        ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize,
+                            NULL, &type, (LPBYTE)data, &dwDataValueSize);
+
+        if (ret != ERROR_SUCCESS) {
+            break;
+        }
+        if (type != REG_SZ) { /* REG_SZ means a null-terminated string */
+            continue;
+        }
+
+        if (!RegistryToBaseTTNameW((LPWSTR)wname) ) {
+            /* If the filename ends with ".ttf" or ".otf" also accept it.
+             * Not expecting to need to do this for .ttc files.
+             * Also note this code is not mirrored in the "A" (win9x) path.
+             */
+            LPWSTR dot = wcsrchr((LPWSTR)data, L'.');
+            if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0)
+                                  && (wcsicmp(dot, L".otf") != 0))) {
+                continue;  /* not a TT font... */
+            }
+        }
+        registerFontW(fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data);
+    }
+
+    RegCloseKey(hkeyFonts);
+}
+
+/* Obtain all the fontname -> filename mappings.
+ * This is called once and the results returned to Java code which can
+ * use it for lookups to reduce or avoid the need to search font files.
+ */
+JNIEXPORT void JNICALL
+Java_sun_awt_Win32FontManager_populateFontFileNameMap0
+(JNIEnv *env, jclass obj, jobject fontToFileMap,
+ jobject fontToFamilyMap, jobject familyToFontListMap, jobject locale)
+{
     jclass classIDHashMap;
     jclass classIDString;
     jmethodID putMID;
@@ -606,56 +657,13 @@
     EnumFontFamiliesExW(screenDC, &lfw,
                         (FONTENUMPROCW)EnumFamilyNamesW,
                         (LPARAM)(&fmi), 0L);
-
-    /* Use the windows registry to map font names to files */
-    ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                       FONTKEY_NT, 0L, KEY_READ, &hkeyFonts);
-    if (ret != ERROR_SUCCESS) {
-        ReleaseDC(NULL, screenDC);
-        screenDC = NULL;
-        return;
-    }
-
-    ret = RegQueryInfoKeyW(hkeyFonts, NULL, NULL, NULL, NULL, NULL, NULL,
-                           &dwNumValues, &dwMaxValueNameLen,
-                           &dwMaxValueDataLen, NULL, NULL);
+    /* Starting from Windows 10 Preview Build 17704
+     * fonts are installed into user's home folder by default,
+     * and are listed in user's registry section
+     */
+    populateFontFileNameFromRegistryKey(HKEY_CURRENT_USER, &fmi, fontToFileMap);
+    populateFontFileNameFromRegistryKey(HKEY_LOCAL_MACHINE, &fmi, fontToFileMap);
 
-    if (ret != ERROR_SUCCESS ||
-        dwMaxValueNameLen >= MAX_BUFFER ||
-        dwMaxValueDataLen >= MAX_BUFFER) {
-        RegCloseKey(hkeyFonts);
-        ReleaseDC(NULL, screenDC);
-        screenDC = NULL;
-        return;
-    }
-    for (nval = 0; nval < dwNumValues; nval++ ) {
-        dwNameSize = MAX_BUFFER;
-        dwDataValueSize = MAX_BUFFER;
-        ret = RegEnumValueW(hkeyFonts, nval, (LPWSTR)wname, &dwNameSize,
-                            NULL, &type, (LPBYTE)data, &dwDataValueSize);
-
-        if (ret != ERROR_SUCCESS) {
-            break;
-        }
-        if (type != REG_SZ) { /* REG_SZ means a null-terminated string */
-            continue;
-        }
-
-        if (!RegistryToBaseTTNameW((LPWSTR)wname) ) {
-            /* If the filename ends with ".ttf" or ".otf" also accept it.
-             * Not expecting to need to do this for .ttc files.
-             * Also note this code is not mirrored in the "A" (win9x) path.
-             */
-            LPWSTR dot = wcsrchr((LPWSTR)data, L'.');
-            if (dot == NULL || ((wcsicmp(dot, L".ttf") != 0)
-                                  && (wcsicmp(dot, L".otf") != 0))) {
-                continue;  /* not a TT font... */
-            }
-        }
-        registerFontW(&fmi, fontToFileMap, (LPWSTR)wname, (LPWSTR)data);
-    }
-
-    RegCloseKey(hkeyFonts);
     ReleaseDC(NULL, screenDC);
     screenDC = NULL;
 }
--- a/src/java.instrument/share/native/libinstrument/InvocationAdapter.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.instrument/share/native/libinstrument/InvocationAdapter.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -558,32 +558,32 @@
     environment = getJPLISEnvironment(jvmtienv);
 
     /* process the premain calls on the all the JPL agents */
-    if ( environment != NULL ) {
-        jthrowable outstandingException = NULL;
-        /*
-         * Add the jarfile to the system class path
-         */
-        JPLISAgent * agent = environment->mAgent;
-        if (appendClassPath(agent, agent->mJarfile)) {
-            fprintf(stderr, "Unable to add %s to system class path - "
-                    "the system class loader does not define the "
-                    "appendToClassPathForInstrumentation method or the method failed\n",
-                    agent->mJarfile);
-            free((void *)agent->mJarfile);
-            abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART);
-        }
+    if (environment == NULL) {
+        abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART ", getting JPLIS environment failed");
+    }
+    jthrowable outstandingException = NULL;
+    /*
+     * Add the jarfile to the system class path
+     */
+    JPLISAgent * agent = environment->mAgent;
+    if (appendClassPath(agent, agent->mJarfile)) {
+        fprintf(stderr, "Unable to add %s to system class path - "
+                "the system class loader does not define the "
+                "appendToClassPathForInstrumentation method or the method failed\n",
+                agent->mJarfile);
         free((void *)agent->mJarfile);
-        agent->mJarfile = NULL;
+        abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART ", appending to system class path failed");
+    }
+    free((void *)agent->mJarfile);
+    agent->mJarfile = NULL;
 
-        outstandingException = preserveThrowable(jnienv);
-        success = processJavaStart( environment->mAgent,
-                                    jnienv);
-        restoreThrowable(jnienv, outstandingException);
-    }
+    outstandingException = preserveThrowable(jnienv);
+    success = processJavaStart( environment->mAgent, jnienv);
+    restoreThrowable(jnienv, outstandingException);
 
     /* if we fail to start cleanly, bring down the JVM */
     if ( !success ) {
-        abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART);
+        abortJVM(jnienv, JPLIS_ERRORMESSAGE_CANNOTSTART ", processJavaStart failed");
     }
 }
 
--- a/src/java.instrument/share/native/libinstrument/JPLISAgent.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.instrument/share/native/libinstrument/JPLISAgent.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -389,17 +389,17 @@
      */
 
     /*
-     *  First make our emergency fallback InternalError throwable.
+     *  First make our fallback InternalError throwable.
      */
     result = initializeFallbackError(jnienv);
-    jplis_assert(result);
+    jplis_assert_msg(result, "fallback init failed");
 
     /*
      *  Now make the InstrumentationImpl instance.
      */
     if ( result ) {
         result = createInstrumentationImpl(jnienv, agent);
-        jplis_assert(result);
+        jplis_assert_msg(result, "instrumentation instance creation failed");
     }
 
 
@@ -409,7 +409,7 @@
      */
     if ( result ) {
         result = setLivePhaseEventHandlers(agent);
-        jplis_assert(result);
+        jplis_assert_msg(result, "setting of live phase VM handlers failed");
     }
 
     /*
@@ -419,6 +419,7 @@
         result = startJavaAgent(agent, jnienv,
                                 agent->mAgentClassName, agent->mOptionsString,
                                 agent->mPremainCaller);
+        jplis_assert_msg(result, "agent load/premain call failed");
     }
 
     /*
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/EventSupport.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/EventSupport.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,20 +78,20 @@
  *When a context no longer needs this EventSupport, it should invoke
  *cleanup() on it.
  *<p>
- *<h4>Registration</h4>
+ *<h2>Registration</h2>
  *When a registration request is made, this class attempts to find an
  *existing notifier that's already working on the request. If one is
  *found, the listener is added to the notifier's list. If one is not found,
  *a new notifier is created for the listener.
  *
- *<h4>Deregistration</h4>
+ *<h2>Deregistration</h2>
  *When a deregistration request is made, this class attempts to find its
  *corresponding notifier. If the notifier is found, the listener is removed
  *from the notifier's list. If the listener is the last listener on the list,
  *the notifier's thread is terminated and removed from this class's hashtable.
  *Nothing happens if the notifier is not found.
  *
- *<h4>Event Dispatching</h4>
+ *<h2>Event Dispatching</h2>
  *The notifiers are responsible for gather information for generating events
  *requested by their respective listeners. When a notifier gets sufficient
  *information to generate an event, it creates invokes the
@@ -101,7 +101,7 @@
  *This class maintains an event queue and a dispatching thread that dequeues
  *events from the queue and dispatches them to the listeners.
  *
- *<h4>Synchronization</h4>
+ *<h2>Synchronization</h2>
  *This class is used by the main thread (LdapCtx) to add/remove listeners.
  *It is also used asynchronously by NamingEventNotifiers threads and
  *the context's Connection thread. It is used by the notifier threads to
--- a/src/java.naming/share/classes/javax/naming/CompositeName.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.naming/share/classes/javax/naming/CompositeName.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
  * The most significant component is at index 0.
  * An empty composite name has no components.
  *
- * <h1>JNDI Composite Name Syntax</h1>
+ * <h2>JNDI Composite Name Syntax</h2>
  * JNDI defines a standard string representation for composite names. This
  * representation is the concatenation of the components of a composite name
  * from left to right using the component separator (a forward
@@ -73,7 +73,7 @@
  * a separator) denotes a trailing empty component.
  * Adjacent component separators denote an empty component.
  *
- *<h1>Composite Name Examples</h1>
+ *<h2>Composite Name Examples</h2>
  *This table shows examples of some composite names. Each row shows
  *the string form of a composite name and its corresponding structural form
  *({@code CompositeName}).
@@ -140,7 +140,7 @@
 </tbody>
 </table>
  *
- *<h1>Composition Examples</h1>
+ *<h2>Composition Examples</h2>
  * Here are some composition examples.  The right column shows composing
  * string composite names while the left column shows composing the
  * corresponding {@code CompositeName}s.  Notice that composing the
@@ -195,7 +195,7 @@
 </tbody>
 </table>
  *
- *<h1>Multithreaded Access</h1>
+ *<h2>Multithreaded Access</h2>
  * A {@code CompositeName} instance is not synchronized against concurrent
  * multithreaded access. Multiple threads trying to access and modify a
  * {@code CompositeName} should lock the object.
--- a/src/java.naming/share/classes/javax/naming/CompoundName.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.naming/share/classes/javax/naming/CompoundName.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
  * The most significant component is at index 0.
  * An empty compound name has no components.
  *
- * <h1>Compound Name Syntax</h1>
+ * <h2>Compound Name Syntax</h2>
  * The syntax of a compound name is specified using a set of properties:
  *<dl>
  *  <dt>jndi.syntax.direction
@@ -136,7 +136,7 @@
  * so that when the same string is parsed, it will yield the same components
  * of the original compound name.
  *
- *<h1>Multithreaded Access</h1>
+ *<h2>Multithreaded Access</h2>
  * A {@code CompoundName} instance is not synchronized against concurrent
  * multithreaded access. Multiple threads trying to access and modify a
  * {@code CompoundName} should lock the object.
--- a/src/java.naming/share/classes/javax/naming/Context.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.naming/share/classes/javax/naming/Context.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
  * consists of a set of name-to-object bindings.
  * It contains methods for examining and updating these bindings.
  *
- * <h1>Names</h1>
+ * <h2>Names</h2>
  * Each name passed as an argument to a {@code Context} method is relative
  * to that context.  The empty name is used to name the context itself.
  * A name parameter may never be null.
@@ -69,12 +69,12 @@
  * names in a composite namespace, at the discretion of the service
  * provider.
  *
- *<h1>Exceptions</h1>
+ *<h2>Exceptions</h2>
  * All the methods in this interface can throw a {@code NamingException} or
  * any of its subclasses. See {@code NamingException} and their subclasses
  * for details on each exception.
  *
- *<h1>Concurrent Access</h1>
+ *<h2>Concurrent Access</h2>
  * A Context instance is not guaranteed to be synchronized against
  * concurrent access by multiple threads.  Threads that need to access
  * a single Context instance concurrently should synchronize amongst
@@ -91,7 +91,7 @@
  * being followed.
  *
  *
- *<h1>Parameters</h1>
+ *<h2>Parameters</h2>
  * A {@code Name} parameter passed to any method of the
  * {@code Context} interface or one of its subinterfaces
  * will not be modified by the service provider.
@@ -103,7 +103,7 @@
  * The caller may subsequently modify it; the service provider may not.
  *
  *
- *<h1>Environment Properties</h1>
+ *<h2>Environment Properties</h2>
  *<p>
  * JNDI applications need a way to communicate various preferences
  * and properties that define the environment in which naming and
@@ -138,7 +138,7 @@
  *
  *<p>
  *<a id=RESOURCEFILES></a>
- *<h1>Resource Files</h1>
+ *<h2>Resource Files</h2>
  *<p>
  * To simplify the task of setting up the environment
  * required by a JNDI application,
@@ -165,7 +165,7 @@
  * There are two kinds of JNDI resource files:
  * <em>provider</em> and <em>application</em>.
  *
- * <h2>Provider Resource Files</h2>
+ * <h3>Provider Resource Files</h3>
  *
  * Each service provider has an optional resource that lists properties
  * specific to that provider.  The name of this resource is:
@@ -200,7 +200,7 @@
  * The service provider's documentation should clearly state which
  * properties are allowed; other properties in the file will be ignored.
  *
- * <h2>Application Resource Files</h2>
+ * <h3>Application Resource Files</h3>
  *
  * When an application is deployed, it will generally have several
  * codebase directories and JARs in its classpath. JNDI locates (using
@@ -228,7 +228,7 @@
  * collects and uses all of these export lists when searching for factory
  * classes.
  *
- * <h2>Search Algorithm for Properties</h2>
+ * <h3>Search Algorithm for Properties</h3>
  *
  * When JNDI constructs an initial context, the context's environment
  * is initialized with properties defined in the environment parameter
--- a/src/java.naming/share/classes/javax/naming/directory/DirContext.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.naming/share/classes/javax/naming/directory/DirContext.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
  * methods for examining and updating attributes
  * associated with objects, and for searching the directory.
  *
- * <h1>Names</h1>
+ * <h2>Names</h2>
  * Each name passed as an argument to a {@code DirContext} method is relative
  * to that context.  The empty name is used to name the context itself.
  * The name parameter may never be null.
@@ -51,7 +51,7 @@
  * name argument to the {@code Context} methods. These same rules
  * apply to the name argument to the {@code DirContext} methods.
  *
- * <h1>Attribute Models</h1>
+ * <h2>Attribute Models</h2>
  * There are two basic models of what attributes should be
  * associated with.  First, attributes may be directly associated with a
  * DirContext object.
@@ -81,7 +81,7 @@
  * whether an object's attributes are stored as part of the object, or stored
  * within the parent object and associated with the object's name.
  *
- * <h1>Attribute Type Names</h1>
+ * <h2>Attribute Type Names</h2>
  * In the {@code getAttributes()} and {@code search()} methods,
  * you can supply the attributes to return by supplying a list of
  * attribute names (strings).
@@ -113,7 +113,7 @@
  * </ul>
  *
  *
- *<h1>Operational Attributes</h1>
+ *<h2>Operational Attributes</h2>
  *<p>
  * Some directories have the notion of "operational attributes" which are
  * attributes associated with a directory object for administrative
@@ -127,7 +127,7 @@
  * In order to retrieve operational attributes, you must name them explicitly.
  *
  *
- * <h1>Named Context</h1>
+ * <h2>Named Context</h2>
  * <p>
  * There are certain methods in which the name must resolve to a context
  * (for example, when searching a single level context). The documentation
@@ -138,7 +138,7 @@
  * Aside from these methods, there is no requirement that the
  * <em>named object</em> be a DirContext.
  *
- *<h1>Parameters</h1>
+ *<h2>Parameters</h2>
  *<p>
  * An {@code Attributes}, {@code SearchControls}, or array object
  * passed as a parameter to any method will not be modified by the
@@ -150,7 +150,7 @@
  * the caller.  The caller may subsequently modify it; the service
  * provider will not.
  *
- *<h1>Exceptions</h1>
+ *<h2>Exceptions</h2>
  *<p>
  * All the methods in this interface can throw a NamingException or
  * any of its subclasses. See NamingException and their subclasses
--- a/src/java.naming/share/classes/javax/naming/event/EventContext.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.naming/share/classes/javax/naming/event/EventContext.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
  * Contains methods for registering/deregistering listeners to be notified of
  * events fired when objects named in a context changes.
  *
- *<h1>Target</h1>
+ *<h2>Target</h2>
  * The name parameter in the {@code addNamingListener()} methods is referred
  * to as the <em>target</em>. The target, along with the scope, identify
  * the object(s) that the listener is interested in.
@@ -59,7 +59,7 @@
  * whether an {@code EventContext} supports registration
  * of nonexistent targets.
  *
- *<h1>Event Source</h1>
+ *<h2>Event Source</h2>
  * The {@code EventContext} instance on which you invoke the
  * registration methods is the <em>event source</em> of the events that are
  * (potentially) generated.
@@ -93,7 +93,7 @@
  * it needs to keep a reference to the listener in order to remove it
  * later). It cannot expect to do a {@code lookup()} and get another instance of
  * an {@code EventContext} on which to perform the deregistration.
- *<h1>Lifetime of Registration</h1>
+ *<h2>Lifetime of Registration</h2>
  * A registered listener becomes deregistered when:
  *<ul>
  *<li>It is removed using {@code removeNamingListener()}.
@@ -105,7 +105,7 @@
  * Until that point, an {@code EventContext} instance that has outstanding
  * listeners will continue to exist and be maintained by the service provider.
  *
- *<h1>Listener Implementations</h1>
+ *<h2>Listener Implementations</h2>
  * The registration/deregistration methods accept an instance of
  * {@code NamingListener}. There are subinterfaces of {@code NamingListener}
  * for different of event types of {@code NamingEvent}.
@@ -118,7 +118,7 @@
  * of the listeners, this allows some service providers to optimize the
  * registration.
  *
- *<h1>Threading Issues</h1>
+ *<h2>Threading Issues</h2>
  *
  * Like {@code Context} instances in general, instances of
  * {@code EventContext} are not guaranteed to be thread-safe.
--- a/src/java.naming/share/classes/javax/naming/ldap/LdapContext.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.naming/share/classes/javax/naming/ldap/LdapContext.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
  * operations, the more generic {@code javax.naming.directory.DirContext}
  * should be used instead.
  *
- * <h3>Usage Details About Controls</h3>
+ * <h2>Usage Details About Controls</h2>
  *
  * This interface provides support for LDAP v3 controls.
  * At a high level, this support allows a user
@@ -50,7 +50,7 @@
  * both the user program and service providers need to understand in order
  * to correctly use request and response controls.
  *
- * <h3>Request Controls</h3>
+ * <h2>Request Controls</h2>
  * <p>
  * There are two types of request controls:
  * <ul>
@@ -75,7 +75,7 @@
  *<p>Unless explicitly qualified, the term "request controls" refers to
  * context request controls.
  *
- * <h4>Context Request Controls</h4>
+ * <h3>Context Request Controls</h3>
  * There are two ways in which a context instance gets its request controls:
  * <ol>
  * <li><code>ldapContext.newInstance(<strong>reqCtls</strong>)</code>
@@ -97,7 +97,7 @@
  * A context instance's request controls are retrieved using
  * the method {@code getRequestControls()}.
  *
- * <h4>Connection Request Controls</h4>
+ * <h3>Connection Request Controls</h3>
  * There are three ways in which connection request controls are set:
  * <ol>
  * <li><code>
@@ -133,7 +133,7 @@
  * A context instance's connection request controls are retrieved using
  * the method {@code getConnectControls()}.
  *
- * <h4>Service Provider Requirements</h4>
+ * <h3>Service Provider Requirements</h3>
  *
  * A service provider supports connection and context request controls
  * in the following ways.  Context request controls must be associated on
@@ -143,7 +143,7 @@
  * property "java.naming.ldap.control.connect" and pass this environment
  * property on to context instances that it creates.
  *
- * <h3>Response Controls</h3>
+ * <h2>Response Controls</h2>
  *
  * The method {@code LdapContext.getResponseControls()} is used to
  * retrieve the response controls generated by LDAP operations executed
@@ -153,7 +153,7 @@
  * To get only the reconnection response controls,
  * use {@code reconnect()} followed by {@code getResponseControls()}.
  *
- * <h3>Parameters</h3>
+ * <h2>Parameters</h2>
  *
  * A {@code Control[]} array
  * passed as a parameter to any method is owned by the caller.
--- a/src/java.net.http/share/classes/java/net/http/HttpResponse.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.net.http/share/classes/java/net/http/HttpResponse.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -828,7 +828,7 @@
     /**
      * A {@code BodySubscriber} consumes response body bytes and converts them
      * into a higher-level Java type.  The class {@link BodySubscribers
-     * BodySubscriber} provides implementations of many common body subscribers.
+     * BodySubscribers} provides implementations of many common body subscribers.
      *
      * <p> The object acts as a {@link Flow.Subscriber}&lt;{@link List}&lt;{@link
      * ByteBuffer}&gt;&gt; to the HTTP Client implementation, which publishes
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -92,7 +92,8 @@
         return delegate.getLocalCertificates();
     }
 
-    @Deprecated
+    @SuppressWarnings("removal")
+    @Deprecated(since="11", forRemoval=true)
     public javax.security.cert.X509Certificate [] getPeerCertificateChain()
             throws SSLPeerUnverifiedException {
         return delegate.getPeerCertificateChain();
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableSSLSession.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableSSLSession.java	Tue Mar 26 09:05:10 2019 -0400
@@ -91,7 +91,8 @@
         return delegate.getLocalCertificates();
     }
 
-    @Deprecated
+    @SuppressWarnings("removal")
+    @Deprecated(since="11", forRemoval=true)
     public javax.security.cert.X509Certificate [] getPeerCertificateChain()
             throws SSLPeerUnverifiedException {
         return delegate.getPeerCertificateChain();
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/package-info.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/package-info.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ *  Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  *  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  *  This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
  * by the Test Compatibility Kit (TCK) as mandated by the Java Community Process.
  * <br>
  *
- * <h3>1.0 Available JDBC RowSet Reference Implementations </h3>
+ * <h2>1.0 Available JDBC RowSet Reference Implementations </h2>
  * The following implementations are provided:<br>
  *
  * <blockquote><code><b>JdbcRowSetImpl</b></code> - The <code>javax.sql.rowset.JdbcRowSet</code>
@@ -53,7 +53,7 @@
  * SPI and helper classes are provided in the interface definitions in the <code>javax.sql.rowset</code>
  * package specification.<br>
  *
- * <h3>2.0 Usage</h3>
+ * <h2>2.0 Usage</h2>
  * The reference implementations represent robust implementations of the standard
  * <code>RowSet</code> interfaces defined in the <code>javax.sql.rowset</code> package.
  * All disconnected <code>RowSet</code> implementations, such as the <code>CachedRowSetImpl</code>
@@ -63,7 +63,7 @@
  * to use these implementations and integrate them into their products just as they
  * can with to other components of the Java platform.<br>
  *
- * <h3>3.0 Extending the JDBC RowSet Implementations</h3>
+ * <h2>3.0 Extending the JDBC RowSet Implementations</h2>
  *
  * The JDBC <code>RowSet</code> reference implementations are provided as non-final
  * classes so that any developer can extend them to provide additional features
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
  * providing optimistic synchronization with a relational datastore
  * using any JDBC technology-enabled driver.
  *
- * <h3>1.0 Backgroud</h3>
+ * <h2>1.0 Backgroud</h2>
  * This synchronization provider is registered with the
  * <code>SyncFactory</code> by default as the
  * <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
@@ -56,7 +56,7 @@
  * <code>RIOptimisticProvider</code> will not write any of the changes to the data
  * source and  will throw a <code>SyncProviderException</code> object.
  *
- * <h3>2.0 Usage</h3>
+ * <h2>2.0 Usage</h2>
  * Standard disconnected <code>RowSet</code> implementations may opt to use this
  * <code>SyncProvider</code> implementation in one of two ways:
  * <OL>
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/providers/RIXMLProvider.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/providers/RIXMLProvider.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
  * with the ability to read and write rowsets in well formed XML using the
  * standard WebRowSet schema.
  *
- * <h3>1.0 Background</h3>
+ * <h2>1.0 Background</h2>
  * This synchronization provider is registered with the
  * <code>SyncFactory</code> by default as the
  * <code>com.sun.rowset.providers.RIXMLProvider</code>.
@@ -51,7 +51,7 @@
  * The <code>RIXMLProvider</code> implementation has a synchronization level of
  * GRADE_NONE, which means that it does no checking at all for conflicts.  It
  * simply writes a <code>WebRowSet</code> object to a file.
- * <h3>2.0 Usage</h3>
+ * <h2>2.0 Usage</h2>
  * A <code>WebRowSet</code> implementation is created with an <code>RIXMLProvider</code>
  * by default.
  * <pre>
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/providers/package-info.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/providers/package-info.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
  * the default <code>SyncProvider</code> implementations and are accessible via the
  * <code>SyncProvider</code> SPI managed by the <code>SyncFactory</code>.
  *
- * <h3>1.0 <code>SyncProvider</code> Reference Implementations</h3>
+ * <h2>1.0 <code>SyncProvider</code> Reference Implementations</h2>
  *   The main job of a <code>SyncProvider</code> implementation is to manage
  * the reader and writer mechanisms.
  *  The <code>SyncProvider</code> SPI, as specified in the <code>javax.sql.rowset.spi</code>
@@ -106,7 +106,7 @@
  * definition.<br>
  * </UL>
  *
- * <h3>2.0 Basics in RowSet Population &amp; Synchronization</h3>
+ * <h2>2.0 Basics in RowSet Population &amp; Synchronization</h2>
  * A rowset's first task is to populate itself with rows of column values.
  * Generally,   these rows will come from a relational database, so a rowset
  * has properties   that supply what is necessary for making a connection to
@@ -147,7 +147,7 @@
  *  once again disconnects itself.<br>
  *   </p>
  *
- * <h3> 3.0 Other Possible Implementations</h3>
+ * <h2> 3.0 Other Possible Implementations</h2>
  *  There are many other possible implementations of the <code>SyncProvider</code> abstract
  *  class. One possibility is to employ a more robust synchronization model, which
  *  would give a <code>RowSet</code> object increased trust in the provider's
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/BaseRowSet.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
  * The basic functions include having properties and sending event notifications,
  * which all JavaBeans&trade; components must implement.
  *
- * <h3>1.0 Overview</h3>
+ * <h2>1.0 Overview</h2>
  * The <code>BaseRowSet</code> class provides the core functionality
  * for all <code>RowSet</code> implementations,
  * and all standard implementations <b>may</b> use this class in combination with
@@ -72,7 +72,7 @@
  *  </ul>
  * </UL>
  *
- * <h3>2.0 Setting Properties</h3>
+ * <h2>2.0 Setting Properties</h2>
  * All rowsets maintain a set of properties, which will usually be set using
  * a tool.  The number and kinds of properties a rowset has will vary,
  * depending on what the <code>RowSet</code> implementation does and how it gets
@@ -95,7 +95,7 @@
  * Interface&trade; (JNDI) API.  This registration
  * is usually done by a person acting in the capacity of a system administrator.
  *
- * <h3>3.0 Setting the Command and Its Parameters</h3>
+ * <h2>3.0 Setting the Command and Its Parameters</h2>
  * When a rowset gets its data from a relational database, it executes a command (a query)
  * that produces a <code>ResultSet</code> object.  This query is the command that is set
  * for the <code>RowSet</code> object's command property.  The rowset populates itself with data by reading the
@@ -143,7 +143,7 @@
  * <code>SerialArray</code>, <code>SerialClob</code>, <code>SerialBlob</code>
  * and <code>SerialRef</code> objects respectively.
  *
- * <h3>4.0 Handling of Parameters Behind the Scenes</h3>
+ * <h2>4.0 Handling of Parameters Behind the Scenes</h2>
  *
  * NOTE: The <code>BaseRowSet</code> class provides two kinds of setter methods,
  * those that set properties and those that set placeholder parameters. The setter
@@ -227,7 +227,7 @@
 * <code>RowSet</code> implementations extending this class; it is not normally called by an
 * application programmer directly.
 *
-* <h3>5.0 Event Notification</h3>
+* <h2>5.0 Event Notification</h2>
 * The <code>BaseRowSet</code> class provides the event notification
 * mechanism for rowsets.  It contains the field
 * <code>listeners</code>, methods for adding and removing listeners, and
@@ -255,7 +255,7 @@
 * What the listener does with this information, which may be nothing, depends on how it was
 * implemented.
 *
-* <h3>6.0 Default Behavior</h3>
+* <h2>6.0 Default Behavior</h2>
 * A default <code>BaseRowSet</code> object is initialized with many starting values.
 *
 * The following is true of a default <code>RowSet</code> instance that extends
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/CachedRowSet.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/CachedRowSet.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,7 @@
  * over the wire to a thin client such as a personal digital assistant (PDA).
  *
  *
- * <h3>1.0 Creating a <code>CachedRowSet</code> Object</h3>
+ * <h2>1.0 Creating a <code>CachedRowSet</code> Object</h2>
  * The following line of code uses the default constructor for
  * <code>CachedRowSet</code>
  * supplied in the reference implementation (RI) to create a default
@@ -140,7 +140,7 @@
  * more details.
  *
  *
- * <h3>2.0 Retrieving Data from a <code>CachedRowSet</code> Object</h3>
+ * <h2>2.0 Retrieving Data from a <code>CachedRowSet</code> Object</h2>
  * Data is retrieved from a <code>CachedRowSet</code> object by using the
  * getter methods inherited from the <code>ResultSet</code>
  * interface.  The following examples, in which <code>crs</code> is a
@@ -171,7 +171,7 @@
  *        System.out.println(name + "  " + id + "  " + comment + "  " + dept);
  *    }
  * </PRE>
- * <h4>2.1 Retrieving <code>RowSetMetaData</code></h4>
+ * <h3>2.1 Retrieving <code>RowSetMetaData</code></h3>
  * An application can get information about the columns in a <code>CachedRowSet</code>
  * object by calling <code>ResultSetMetaData</code> and <code>RowSetMetaData</code>
  * methods on a <code>RowSetMetaData</code> object. The following code fragment,
@@ -207,7 +207,7 @@
  * override the <code>getMetaData()</code> method defined in
  * <code>java.sql.ResultSet</code> and return a <code>RowSetMetaData</code> object.
  *
- * <h3>3.0 Updating a <code>CachedRowSet</code> Object</h3>
+ * <h2>3.0 Updating a <code>CachedRowSet</code> Object</h2>
  * Updating a <code>CachedRowSet</code> object is similar to updating a
  * <code>ResultSet</code> object, but because the rowset is not connected to
  * its data source while it is being updated, it must take an additional step
@@ -261,7 +261,7 @@
  * and <code>insertRow</code> have been made.  If <code>acceptChanges</code>
  * is called only once, only one connection needs to be established.
  *
- * <h3>4.0 Updating the Underlying Data Source</h3>
+ * <h2>4.0 Updating the Underlying Data Source</h2>
  * When the method <code>acceptChanges</code> is executed, the
  * <code>CachedRowSet</code> object's writer, a <code>RowSetWriterImpl</code>
  * object, is called behind the scenes to write the changes made to the
@@ -305,7 +305,7 @@
  * Whether a writer checks for conflicts, what degree of checking it does, and how
  * it handles conflicts all depend on how it is implemented.
  *
- * <h3>5.0 Registering and Notifying Listeners</h3>
+ * <h2>5.0 Registering and Notifying Listeners</h2>
  * Being JavaBeans components, all rowsets participate in the JavaBeans event
  * model, inheriting methods for registering listeners and notifying them of
  * changes from the <code>BaseRowSet</code> class.  A listener for a
@@ -328,7 +328,7 @@
  * <code>table</code> and <code>barGraph</code> will be notified when there is
  * a change in <code>crs</code>.
  *
- * <h3>6.0 Passing Data to Thin Clients</h3>
+ * <h2>6.0 Passing Data to Thin Clients</h2>
  * One of the main reasons to use a <code>CachedRowSet</code> object is to
  * pass data between different components of an application. Because it is
  * serializable, a <code>CachedRowSet</code> object can be used, for example,
@@ -344,7 +344,7 @@
  * Thus, a <code>CachedRowSet</code> object provides a means to "get rows in"
  * without the need to implement the full JDBC API.
  *
- * <h3>7.0 Scrolling and Updating</h3>
+ * <h2>7.0 Scrolling and Updating</h2>
  * A second major use for <code>CachedRowSet</code> objects is to provide
  * scrolling and updating for <code>ResultSet</code> objects that
  * do not provide these capabilities themselves.  In other words, a
@@ -378,7 +378,7 @@
  * <code>CachedRowSet</code> object does have a limitation: It is limited in
  * size by the amount of data it can store in memory at one time.
  *
- * <h3>8.0 Getting Universal Data Access</h3>
+ * <h2>8.0 Getting Universal Data Access</h2>
  * Another advantage of the <code>CachedRowSet</code> class is that it makes it
  * possible to retrieve and store data from sources other than a relational
  * database. The reader for a rowset can be implemented to read and populate
@@ -391,7 +391,7 @@
  * <code>CachedRowSet</code> objects will contain data that was fetched
  * from an SQL database using the JDBC API.
  *
- * <h3>9.0 Setting Properties</h3>
+ * <h2>9.0 Setting Properties</h2>
  * All rowsets maintain a set of properties, which will usually be set using
  * a tool.  The number and kinds of properties a rowset has will vary,
  * depending on what the rowset does and how it gets its data.  For example,
@@ -492,7 +492,7 @@
  *    crs.execute();
  * }</PRE>
  *
- * <h3>10.0 Paging Data</h3>
+ * <h2>10.0 Paging Data</h2>
  * Because a <code>CachedRowSet</code> object stores data in memory,
  * the amount of data that it can contain at any one
  * time is determined by the amount of memory available. To get around this limitation,
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/FilteredRowSet.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/FilteredRowSet.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,7 +38,7 @@
  * Alternatively, a vendor is free to implement its own version
  * by implementing this interface.
  *
- * <h3>1.0 Background</h3>
+ * <h2>1.0 Background</h2>
  *
  * There are occasions when a <code>RowSet</code> object has a need to provide a degree
  * of filtering to its contents. One possible solution is to provide
@@ -56,14 +56,14 @@
  * methods, which a <code>FilteredRowSet</code> implementation can override
  * to supply filtering support.
  *
- * <h3>2.0 Predicate Sharing</h3>
+ * <h2>2.0 Predicate Sharing</h2>
  *
  * If a <code>FilteredRowSet</code> implementation is shared using the
  * inherited <code>createShared</code> method in parent interfaces, the
  * <code>Predicate</code> should be shared without modification by all
  * <code>FilteredRowSet</code> instance clones.
  *
- * <h3>3.0 Usage</h3>
+ * <h2>3.0 Usage</h2>
  * <p>
  * By implementing a <code>Predicate</code> (see example in <a href="Predicate.html">Predicate</a>
  * class JavaDoc), a <code>FilteredRowSet</code> could then be used as described
@@ -92,7 +92,7 @@
  * used in combination to achieved the required filtering result with
  * out the need for query language processing.
  *
- * <h3>4.0 Updating a <code>FilteredRowSet</code> Object</h3>
+ * <h2>4.0 Updating a <code>FilteredRowSet</code> Object</h2>
  * The predicate set on a <code>FilteredRowSet</code> object
  * applies a criterion on all rows in a
  * <code>RowSet</code> object to manage a subset of rows in a <code>RowSet</code>
@@ -113,7 +113,7 @@
  * <code>FilteredRowSet</code> object, and all subsequent views and updates will be
  * subject to similar enforcement.
  *
- * <h3>5.0 Behavior of Rows Outside the Filter</h3>
+ * <h2>5.0 Behavior of Rows Outside the Filter</h2>
  * Rows that fall outside of the filter set on a <code>FilteredRowSet</code>
  * object cannot be modified until the filter is removed or a
  * new filter is applied.
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/JdbcRowSet.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/JdbcRowSet.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
  * The standard interface that all standard implementations of
  * <code>JdbcRowSet</code> must implement.
  *
- * <h3>1.0 Overview</h3>
+ * <h2>1.0 Overview</h2>
  * A wrapper around a <code>ResultSet</code> object that makes it possible
  * to use the result set as a JavaBeans&trade;
  * component.  Thus, a <code>JdbcRowSet</code> object can be one of the Beans that
@@ -60,7 +60,7 @@
  * <code>JdbcRowSet</code> object as if it were the <code>ResultSet</code>
  * object.
  *
- * <h3>2.0 Creating a <code>JdbcRowSet</code> Object</h3>
+ * <h2>2.0 Creating a <code>JdbcRowSet</code> Object</h2>
  * The reference implementation of the <code>JdbcRowSet</code> interface,
  * <code>JdbcRowSetImpl</code>, provides an implementation of
  * the default constructor.  A new instance is initialized with
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/JoinRowSet.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/JoinRowSet.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
  * alternatively be set by supplying it to the appropriate version of the
  * <code>JointRowSet</code> method <code>addRowSet</code>.
  *
- * <h3>1.0 Overview</h3>
+ * <h2>1.0 Overview</h2>
  * Disconnected <code>RowSet</code> objects (<code>CachedRowSet</code> objects
  * and implementations extending the <code>CachedRowSet</code> interface)
  * do not have a standard way to establish an SQL <code>JOIN</code> between
@@ -98,7 +98,7 @@
  * <code>JoinRowSet</code> interface explain these <code>JOIN</code> types, which are
  * standard SQL <code>JOIN</code> types.
  *
- * <h3>2.0 Using a <code>JoinRowSet</code> Object for Creating a <code>JOIN</code></h3>
+ * <h2>2.0 Using a <code>JoinRowSet</code> Object for Creating a <code>JOIN</code></h2>
  * When a <code>JoinRowSet</code> object is created, it is empty.
  * The first <code>RowSet</code> object to be added becomes the basis for the
  * <code>JOIN</code> relationship.
@@ -126,7 +126,7 @@
  *  These four methods set or reset the match column at the time a <code>RowSet</code>
  *  object is being added to a <code>JoinRowSet</code> object.
  * </ul>
- * <h3>3.0 Sample Usage</h3>
+ * <h2>3.0 Sample Usage</h2>
  * <p>
  * The following code fragment adds two <code>CachedRowSet</code>
  * objects to a <code>JoinRowSet</code> object. Note that in this example,
@@ -193,7 +193,7 @@
  * <code>EMP_ID</code> column matches a value for the <code>EMP_ID</code> column
  * in <i>jrs</i> has been added to <i>jrs</i>.
  *
- * <h3>4.0 <code>JoinRowSet</code> Methods</h3>
+ * <h2>4.0 <code>JoinRowSet</code> Methods</h2>
  * The <code>JoinRowSet</code> interface supplies several methods for adding
  * <code>RowSet</code> objects and for getting information about the
  * <code>JoinRowSet</code> object.
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/Joinable.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/Joinable.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 import java.sql.SQLException;
 
 /**
- * <h3>1.0 Background</h3>
+ * <h2>1.0 Background</h2>
  * The <code>Joinable</code> interface provides the methods for getting and
  * setting a match column, which is the basis for forming the SQL <code>JOIN</code>
  * formed by adding <code>RowSet</code> objects to a <code>JoinRowSet</code>
@@ -58,7 +58,7 @@
  *     }
  * </pre>
  *
- * <h3>2.0 Usage Guidelines</h3>
+ * <h2>2.0 Usage Guidelines</h2>
  * <P>
  * The methods in the <code>Joinable</code> interface allow a <code>RowSet</code> object
  * to set a match column, retrieve a match column, or unset a match column, which is
@@ -98,7 +98,7 @@
  * become part of an SQL <code>JOIN</code> directly without having to become part
  * of a <code>JoinRowSet</code> object.
  *
- * <h3>3.0 Managing Multiple Match Columns</h3>
+ * <h2>3.0 Managing Multiple Match Columns</h2>
  * The index array passed into the <code>setMatchColumn</code> methods indicates
  * how many match columns are being set (the length of the array) in addition to
  * which columns will be used for the match. For example:
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/Predicate.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/Predicate.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
  * The standard interface that provides the framework for all
  * <code>FilteredRowSet</code> objects to describe their filters.
  *
- * <h3>1.0 Background</h3>
+ * <h2>1.0 Background</h2>
  * The <code>Predicate</code> interface is a standard interface that
  * applications can implement to define the filter they wish to apply to a
  * a <code>FilteredRowSet</code> object. A <code>FilteredRowSet</code>
@@ -43,7 +43,7 @@
  * the constraints of the filter; and conversely, it inserts, modifies, or updates
  * only rows that are within the constraints of the filter.
  *
- * <h3>2.0 Implementation Guidelines</h3>
+ * <h2>2.0 Implementation Guidelines</h2>
  * In order to supply a predicate for the <code>FilteredRowSet</code>.
  * this interface must be implemented.  At this time, the JDBC RowSet
  * Implementations (JSR-114) does not specify any standard filters definitions.
@@ -101,7 +101,7 @@
  *
  */
 
- // <h3>3.0 FilteredRowSet Internals</h3>
+ // <h2>3.0 FilteredRowSet Internals</h2>
  // internalNext, First, Last. Discuss guidelines on how to approach this
  // and cite examples in reference implementations.
 public interface Predicate {
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/WebRowSet.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/WebRowSet.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
  * The standard interface that all implementations of a {@code WebRowSet}
  * must implement.
  *
- * <h3>1.0 Overview</h3>
+ * <h2>1.0 Overview</h2>
  * The {@code WebRowSetImpl} provides the standard
  * reference implementation, which may be extended if required.
  * <P>
@@ -78,12 +78,12 @@
  * </li>
  * </ul>
  *
- * <h3>2.0 WebRowSet States</h3>
+ * <h2>2.0 WebRowSet States</h2>
  * The following sections demonstrates how a {@code WebRowSet} implementation
  * should use the XML Schema to describe update, insert, and delete operations
  * and to describe the state of a {@code WebRowSet} object in XML.
  *
- * <h4>2.1 State 1 - Outputting a {@code WebRowSet} Object to XML</h4>
+ * <h2>2.1 State 1 - Outputting a {@code WebRowSet} Object to XML</h2>
  * In this example, a {@code WebRowSet} object is created and populated with a simple 2 column,
  * 5 row table from a data source. Having the 5 rows in a {@code WebRowSet} object
  * makes it possible to describe them in XML. The
@@ -216,7 +216,7 @@
  *      </currentRow>
  * </data>
  * }</PRE>
- * <h4>2.2 State 2 - Deleting a Row</h4>
+ * <h2>2.2 State 2 - Deleting a Row</h2>
  * Deleting a row in a {@code WebRowSet} object involves simply moving to the row
  * to be deleted and then calling the method {@code deleteRow}, as in any other
  * {@code RowSet} object.  The following
@@ -265,7 +265,7 @@
  *      </currentRow>
  * </data>
  *} </PRE>
- * <h4>2.3 State 3 - Inserting a Row</h4>
+ * <h2>2.3 State 3 - Inserting a Row</h2>
  * A {@code WebRowSet} object can insert a new row by moving to the insert row,
  * calling the appropriate updater methods for each column in the row, and then
  * calling the method {@code insertRow}.
@@ -337,7 +337,7 @@
  *      </currentRow>
  * </date>
  *} </PRE>
- * <h4>2.4 State 4 - Modifying a Row</h4>
+ * <h2>2.4 State 4 - Modifying a Row</h2>
  * Modifying a row produces specific XML that records both the new value and the
  * value that was replaced.  The value that was replaced becomes the original value,
  * and the new value becomes the current value. The following
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialArray.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialArray.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@
  * if necessary. At this time, logical pointers to the data in the data source,
  * such as locators, are not currently supported.
  *
- * <h3> Thread safety </h3>
+ * <h2> Thread safety </h2>
  *
  * A SerialArray is not safe for use by multiple concurrent threads.  If a
  * SerialArray is to be used by more than one thread then access to the
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialBlob.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialBlob.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@
  * <code>Blob</code> object within a <code>SerialBlob</code> object
  * and to update or truncate a <code>Blob</code> object.
  *
- * <h3> Thread safety </h3>
+ * <h2> Thread safety </h2>
  *
  * <p> A SerialBlob is not safe for use by multiple concurrent threads.  If a
  * SerialBlob is to be used by more than one thread then access to the SerialBlob
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialClob.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialClob.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
  * from a <code>SerialClob</code> object or to locate the start of
  * a pattern of characters.
  *
- * <h3> Thread safety </h3>
+ * <h2> Thread safety </h2>
  *
  * <p> A SerialClob is not safe for use by multiple concurrent threads.  If a
  * SerialClob is to be used by more than one thread then access to the SerialClob
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialDatalink.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialDatalink.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
  *      java.net.URL url = rowset.getURL(1);
  * </pre>
  *
- * <h3> Thread safety </h3>
+ * <h2> Thread safety </h2>
  *
  * A SerialDatalink is not safe for use by multiple concurrent threads.  If a
  * SerialDatalink is to be used by more than one thread then access to the
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialJavaObject.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialJavaObject.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@
  * Static or transient fields cannot be serialized; an attempt to serialize
  * them will result in a <code>SerialException</code> object being thrown.
  *
- * <h3> Thread safety </h3>
+ * <h2> Thread safety </h2>
  *
  * A SerialJavaObject is not safe for use by multiple concurrent threads.  If a
  * SerialJavaObject is to be used by more than one thread then access to the
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialRef.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialRef.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
  * creating a <code>SerialRef</code> instance from a <code>Ref</code>
  * object and provides methods for getting and setting the <code>Ref</code> object.
  *
- * <h3> Thread safety </h3>
+ * <h2> Thread safety </h2>
  *
  * A SerialRef is not safe for use by multiple concurrent threads.  If a
  * SerialRef is to be used by more than one thread then access to the SerialRef
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialStruct.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SerialStruct.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@
  * the SQL type name of the SQL structured type in the database, and methods
  * for retrieving its attribute values.
  *
- * <h3> Thread safety </h3>
+ * <h2> Thread safety </h2>
  *
  * A SerialStruct is not safe for use by multiple concurrent threads.  If a
  * SerialStruct is to be used by more than one thread then access to the
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/package-info.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/package-info.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
  * a different VM or across layers within an application.<br>
  * </p>
  *
- * <h3>1.0 SerialArray</h3>
+ * <h2>1.0 SerialArray</h2>
  * A serializable mapping in the Java programming language of an SQL ARRAY
  * value. <br>
  * <br>
@@ -43,7 +43,7 @@
  * the SQL name for the base type, and methods for copying all or part of a
  * <code>SerialArray</code> object. <br>
  *
- * <h3>2.0 SerialBlob</h3>
+ * <h2>2.0 SerialBlob</h2>
  * A serializable mapping in the Java programming language of an SQL BLOB
  * value.  <br>
  * <br>
@@ -60,7 +60,7 @@
  * to locate a given pattern of bytes or a <code>Blob</code> object within a <code>SerialBlob</code>
  * object. <br>
  *
- * <h3>3.0 SerialClob</h3>
+ * <h2>3.0 SerialClob</h2>
  * A serializable mapping in the Java programming language of an SQL CLOB
  * value.  <br>
  * <br>
@@ -74,7 +74,7 @@
  * <code>SerialClob</code> object or to locate the start of a pattern of characters.
  * <br>
  *
- * <h3>5.0 SerialDatalink</h3>
+ * <h2>5.0 SerialDatalink</h2>
  * A serializable mapping in the Java programming language of an SQL DATALINK
  * value. A DATALINK value references a file outside of the underlying data source
  * that the originating data source manages. <br>
@@ -85,7 +85,7 @@
  * <br>
  * &nbsp;&nbsp;<code>&nbsp;&nbsp;&nbsp; java.net.URL url = rowset.getURL(1);</code><br>
  *
- * <h3>6.0 SerialJavaObject</h3>
+ * <h2>6.0 SerialJavaObject</h2>
  * A serializable mapping in the Java programming language of an SQL JAVA_OBJECT
  * value. Assuming the Java object instance implements the Serializable interface,
  * this simply wraps the serialization process. <br>
@@ -96,7 +96,7 @@
  * Static or transient fields cannot be serialized and attempting to do so
  * will result in a <code>SerialException</code> being thrown. <br>
  *
- * <h3>7.0 SerialRef</h3>
+ * <h2>7.0 SerialRef</h2>
  * A serializable mapping between the SQL REF type and the Java programming
  * language. <br>
  * <br>
@@ -104,7 +104,7 @@
  * instance from a <code>Ref</code> type and provides methods for getting
  * and setting the <code>Ref</code> object type. <br>
  *
- * <h3>8.0 SerialStruct</h3>
+ * <h2>8.0 SerialStruct</h2>
  * A serializable mapping in the Java programming language of an SQL structured
  * type. Each attribute that is not already serializable is mapped to a serializable
  * form, and if an attribute is itself a structured type, each of its attributes
@@ -119,7 +119,7 @@
  * type name of the SQL structured type in the database, and methods for retrieving
  * its attribute values. <br>
  *
- * <h3>9.0 SQLInputImpl</h3>
+ * <h2>9.0 SQLInputImpl</h2>
  *   An input stream used for custom mapping user-defined types (UDTs). An
  *   <code>SQLInputImpl</code> object is an input stream that contains a stream of
  *   values that are
@@ -142,7 +142,7 @@
  * method <code>SQLData.readSQL</code>,  which in turn calls the <code>SQLInputImpl</code>
  * methods to read the  attributes from the input stream. <br>
  *
- * <h3>10.0 SQLOutputImpl</h3>
+ * <h2>10.0 SQLOutputImpl</h2>
  *   The output stream for writing the attributes of a custom mapped user-defined
  *  type (UDT) back to the database. The driver uses this interface internally,
  *  and its methods are never directly invoked by an application programmer.
@@ -160,7 +160,7 @@
  * <code>SQLOutputImpl</code>
  * output  stream as the representation of an SQL user-defined type.
  *
- * <h3>Custom Mapping</h3>
+ * <h2>Custom Mapping</h2>
  * The JDBC API provides mechanisms for mapping an SQL structured type or DISTINCT
  * type to the Java programming language.  Typically, a structured type is mapped
  * to a class, and its attributes are mapped to fields in the class.
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncFactory.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@
  * <code>RowSet</code> implementation can obtain its <code>SyncProvider</code>
  * implementation.
  *
- * <h3>1.0 Overview</h3>
+ * <h2>1.0 Overview</h2>
  * The <code>SyncFactory</code> class provides an internal registry of available
  * synchronization provider implementations (<code>SyncProvider</code> objects).
  * This registry may be queried to determine which
@@ -108,7 +108,7 @@
  * <code>SyncProvider</code> implementations are available, the reference
  * implementation providers are supplied.
  * </ol>
- * <h3>2.0 Registering <code>SyncProvider</code> Implementations</h3>
+ * <h2>2.0 Registering <code>SyncProvider</code> Implementations</h2>
  * <p>
  * Both vendors and developers can register <code>SyncProvider</code>
  * implementations using one of the following mechanisms.
--- a/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncProvider.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/java.sql.rowset/share/classes/javax/sql/rowset/spi/SyncProvider.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -101,7 +101,7 @@
  * providers for additional guidance on how to implement a new
  * <code>SyncProvider</code> implementation.
  *
- * <h3>2.0 How a <code>RowSet</code> Object Gets Its Provider</h3>
+ * <h2>2.0 How a <code>RowSet</code> Object Gets Its Provider</h2>
  *
  * A disconnected <code>Rowset</code> object may get access to a
  * <code>SyncProvider</code> object in one of the following two ways:
@@ -130,7 +130,7 @@
  * assigned the default provider in the reference implementation, which is
  * <code>com.sun.rowset.providers.RIOptimisticProvider</code>.
  *
- * <h3>3.0 Violations and Synchronization Issues</h3>
+ * <h2>3.0 Violations and Synchronization Issues</h2>
  * If an update between a disconnected <code>RowSet</code> object
  * and a data source violates
  * the original query or the underlying data source constraints, this will
@@ -148,7 +148,7 @@
  * all <code>SyncProvider</code>
  * objects must throw a <code>SyncProviderException</code>.
  *
- * <h3>4.0 Updatable SQL VIEWs</h3>
+ * <h2>4.0 Updatable SQL VIEWs</h2>
  * It is possible for any disconnected or connected <code>RowSet</code> object to be populated
  * from an SQL query that is formulated originally from an SQL <code>VIEW</code>.
  * While in many cases it is possible for an update to be performed to an
@@ -168,7 +168,7 @@
  * The default is for a <code>RowSet</code> object not to be updatable if it was
  * populated with data from an SQL <code>VIEW</code>.
  *
- * <h3>5.0 <code>SyncProvider</code> Constants</h3>
+ * <h2>5.0 <code>SyncProvider</code> Constants</h2>
  * The <code>SyncProvider</code> class provides three sets of constants that
  * are used as return values or parameters for <code>SyncProvider</code> methods.
  * <code>SyncProvider</code> objects may be implemented to perform synchronization
--- a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java	Tue Mar 26 09:05:10 2019 -0400
@@ -3779,7 +3779,8 @@
     }
 
     /*
-     * returns the JMenuItem accelerator
+     * Returns the JMenuItem accelerator. Similar implementation is used on
+     * macOS, see CAccessibility.getAcceleratorText(AccessibleContext).
      */
     private KeyStroke getAccelerator(final AccessibleContext ac) {
         // workaround for getAccessibleKeyBinding not returning the
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Checker.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,6 @@
 import com.sun.source.doctree.IdentifierTree;
 import com.sun.source.doctree.IndexTree;
 import com.sun.source.doctree.InheritDocTree;
-import com.sun.source.doctree.InlineTagTree;
 import com.sun.source.doctree.LinkTree;
 import com.sun.source.doctree.LiteralTree;
 import com.sun.source.doctree.ParamTree;
@@ -140,16 +139,15 @@
     }
 
     private final Deque<TagStackItem> tagStack; // TODO: maybe want to record starting tree as well
-    private HtmlTag currHeaderTag;
+    private HtmlTag currHeadingTag;
 
-    private final int implicitHeaderLevel;
+    private int implicitHeadingRank;
 
     // <editor-fold defaultstate="collapsed" desc="Top level">
 
     Checker(Env env) {
         this.env = Assert.checkNonNull(env);
         tagStack = new LinkedList<>();
-        implicitHeaderLevel = env.implicitHeaderLevel;
     }
 
     public Void scan(DocCommentTree tree, TreePath p) {
@@ -188,7 +186,7 @@
         }
 
         tagStack.clear();
-        currHeaderTag = null;
+        currHeadingTag = null;
 
         foundParams.clear();
         foundThrows.clear();
@@ -196,6 +194,37 @@
         foundReturn = false;
         hasNonWhitespaceText = false;
 
+        switch (p.getLeaf().getKind()) {
+            // the following are for declarations that have their own top-level page,
+            // and so the doc comment comes after the <h1> page title.
+            case MODULE:
+            case PACKAGE:
+            case CLASS:
+            case INTERFACE:
+            case ENUM:
+            case ANNOTATION_TYPE:
+                implicitHeadingRank = 1;
+                break;
+
+            // this is for html files
+            // ... if it is a legacy package.html, the doc comment comes after the <h1> page title
+            // ... otherwise, (e.g. overview file and doc-files/*.html files) no additional headings are inserted
+            case COMPILATION_UNIT:
+                implicitHeadingRank = fo.isNameCompatible("package", JavaFileObject.Kind.HTML) ? 1 : 0;
+                break;
+
+            // the following are for member declarations, which appear in the page
+            // for the enclosing type, and so appear after the <h2> "Members"
+            // aggregate heading and the specific <h3> "Member signature" heading.
+            case METHOD:
+            case VARIABLE:
+                implicitHeadingRank = 3;
+                break;
+
+            default:
+                Assert.error("unexpected tree kind: " + p.getLeaf().getKind() + " " + fo);
+        }
+
         scan(new DocTreePath(p, tree), null);
 
         if (!isOverridingMethod) {
@@ -328,9 +357,9 @@
 
             // tag specific checks
             switch (t) {
-                // check for out of sequence headers, such as <h1>...</h1>  <h3>...</h3>
+                // check for out of sequence headings, such as <h1>...</h1>  <h3>...</h3>
                 case H1: case H2: case H3: case H4: case H5: case H6:
-                    checkHeader(tree, t);
+                    checkHeading(tree, t);
                     break;
             }
 
@@ -446,23 +475,27 @@
         env.messages.error(HTML, tree, "dc.tag.not.allowed.here", treeName);
     }
 
-    private void checkHeader(StartElementTree tree, HtmlTag tag) {
+    private void checkHeading(StartElementTree tree, HtmlTag tag) {
         // verify the new tag
-        if (getHeaderLevel(tag) > getHeaderLevel(currHeaderTag) + 1) {
-            if (currHeaderTag == null) {
-                env.messages.error(ACCESSIBILITY, tree, "dc.tag.header.sequence.1", tag);
+        if (getHeadingRank(tag) > getHeadingRank(currHeadingTag) + 1) {
+            if (currHeadingTag == null) {
+                env.messages.error(ACCESSIBILITY, tree, "dc.tag.heading.sequence.1",
+                        tag, implicitHeadingRank);
             } else {
-                env.messages.error(ACCESSIBILITY, tree, "dc.tag.header.sequence.2",
-                    tag, currHeaderTag);
+                env.messages.error(ACCESSIBILITY, tree, "dc.tag.heading.sequence.2",
+                    tag, currHeadingTag);
             }
+        } else if (getHeadingRank(tag) <= implicitHeadingRank) {
+            env.messages.error(ACCESSIBILITY, tree, "dc.tag.heading.sequence.3",
+                    tag, implicitHeadingRank);
         }
 
-        currHeaderTag = tag;
+        currHeadingTag = tag;
     }
 
-    private int getHeaderLevel(HtmlTag tag) {
+    private int getHeadingRank(HtmlTag tag) {
         if (tag == null)
-            return implicitHeaderLevel;
+            return implicitHeadingRank;
         switch (tag) {
             case H1: return 1;
             case H2: return 2;
@@ -666,11 +699,11 @@
                 break;
 
             case OBSOLETE:
-                env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete", name);
+                env.messages.warning(HTML, tree, "dc.attr.obsolete", name);
                 break;
 
             case USE_CSS:
-                env.messages.warning(ACCESSIBILITY, tree, "dc.attr.obsolete.use.css", name);
+                env.messages.warning(HTML, tree, "dc.attr.obsolete.use.css", name);
                 break;
 
             case HTML5:
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,7 +80,6 @@
     public static final String XMSGS_OPTION = "-Xmsgs";
     public static final String XMSGS_CUSTOM_PREFIX = "-Xmsgs:";
     private static final String STATS = "-stats";
-    public static final String XIMPLICIT_HEADERS = "-XimplicitHeaders:";
     public static final String XCUSTOM_TAGS_PREFIX = "-XcustomTags:";
     public static final String XHTML_VERSION_PREFIX = "-XhtmlVersion:";
     public static final String XCHECK_PACKAGE = "-XcheckPackage:";
@@ -289,9 +288,6 @@
                 env.messages.setOptions(null);
             } else if (arg.startsWith(XMSGS_CUSTOM_PREFIX)) {
                 env.messages.setOptions(arg.substring(arg.indexOf(":") + 1));
-            } else if (arg.matches(XIMPLICIT_HEADERS + "[1-6]")) {
-                char ch = arg.charAt(arg.length() - 1);
-                env.setImplicitHeaders(Character.digit(ch, 10));
             } else if (arg.startsWith(XCUSTOM_TAGS_PREFIX)) {
                 env.setCustomTags(arg.substring(arg.indexOf(":") + 1));
             } else if (arg.startsWith(XHTML_VERSION_PREFIX)) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Env.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Env.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,8 +93,6 @@
     /** Message handler. */
     final Messages messages;
 
-    int implicitHeaderLevel = 0;
-
     Set<String> customTags;
 
     Set<Pattern> includePackages;
@@ -153,10 +151,6 @@
         java_lang_Void = elements.getTypeElement("java.lang.Void").asType();
     }
 
-    void setImplicitHeaders(int n) {
-        implicitHeaderLevel = n;
-    }
-
     void setCustomTags(String cTags) {
         customTags = new LinkedHashSet<>();
         for (String s : cTags.split(DocLint.SEPARATOR)) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/resources/doclint.properties	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/resources/doclint.properties	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -63,8 +63,9 @@
 dc.tag.a.within.a = {0} tag, which expands to <a>, within <a>
 dc.tag.end.not.permitted = invalid end tag: </{0}>
 dc.tag.end.unexpected = unexpected end tag: </{0}>
-dc.tag.header.sequence.1 = header used out of sequence: <{0}>
-dc.tag.header.sequence.2 = header used out of sequence: <{0}>
+dc.tag.heading.sequence.1 = heading used out of sequence: <{0}>, compared to implicit preceding heading: <H{1}>
+dc.tag.heading.sequence.2 = heading used out of sequence: <{0}>, compared to previous heading: <{1}>
+dc.tag.heading.sequence.3 = unexpected heading used: <{0}>, compared to implicit preceding heading: <H{1}>
 dc.tag.nested.not.allowed=nested tag not allowed: <{0}>
 dc.tag.not.allowed.here = tag not allowed here: <{0}>
 dc.tag.not.allowed = element not allowed in documentation comments: <{0}>
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java	Tue Mar 26 09:05:10 2019 -0400
@@ -288,6 +288,11 @@
             return userPath.toString();
         }
 
+        @Override @DefinedBy(Api.COMPILER)
+        public String getShortName() {
+            return userPath.getFileName().toString();
+        }
+
         @Override
         public String inferBinaryName(Iterable<? extends Path> paths) {
             Path absPath = path.toAbsolutePath();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -852,9 +852,6 @@
             doclintOpts.add(DocLint.XHTML_VERSION_PREFIX + format);
         }
 
-        // standard doclet normally generates H1, H2,
-        // so for now, allow user comments to assume that
-        doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2");
         return List.from(doclintOpts.toArray(new String[doclintOpts.size()]));
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Tue Mar 26 09:05:10 2019 -0400
@@ -231,7 +231,7 @@
 compiler.err.cant.apply.symbol=\
     {0} {1} in {4} {5} cannot be applied to given types;\n\
     required: {2}\n\
-    found: {3}\n\
+    found:    {3}\n\
     reason: {6}
 
 # 0: symbol kind, 1: name, 2: list of type
@@ -242,7 +242,7 @@
 compiler.misc.cant.apply.symbol=\
     {0} {1} in {4} {5} cannot be applied to given types\n\
     required: {2}\n\
-    found: {3}\n\
+    found:    {3}\n\
     reason: {6}
 
 # 0: symbol kind, 1: name, 2: list of type
@@ -1952,7 +1952,7 @@
 compiler.warn.unchecked.meth.invocation.applied=\
     unchecked method invocation: {0} {1} in {4} {5} is applied to given types\n\
     required: {2}\n\
-    found: {3}
+    found:    {3}
 
 # 0: type
 compiler.warn.unchecked.generic.array.creation=\
@@ -2880,25 +2880,25 @@
 compiler.err.incorrect.receiver.name=\
     the receiver name does not match the enclosing class type\n\
     required: {0}\n\
-    found: {1}
+    found:    {1}
 
 # 0: type, 1: type
 compiler.err.incorrect.receiver.type=\
     the receiver type does not match the enclosing class type\n\
     required: {0}\n\
-    found: {1}
+    found:    {1}
 
 # 0: type, 1: type
 compiler.err.incorrect.constructor.receiver.type=\
     the receiver type does not match the enclosing outer class type\n\
     required: {0}\n\
-    found: {1}
+    found:    {1}
 
 # 0: type, 1: type
 compiler.err.incorrect.constructor.receiver.name=\
     the receiver name does not match the enclosing outer class type\n\
     required: {0}\n\
-    found: {1}
+    found:    {1}
 
 compiler.err.no.annotations.on.dot.class=\
     no annotations are allowed in the type of a class literal
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Tue Mar 26 09:05:10 2019 -0400
@@ -53,14 +53,10 @@
     public final Name empty;
     public final Name hyphen;
     public final Name one;
-    public final Name period;
-    public final Name semicolon;
     public final Name slash;
-    public final Name slashequals;
 
     // keywords
     public final Name _class;
-    public final Name _default;
     public final Name _super;
     public final Name _this;
     public final Name var;
@@ -83,24 +79,16 @@
     public final Name clinit;
     public final Name clone;
     public final Name close;
-    public final Name compareTo;
     public final Name deserializeLambda;
     public final Name desiredAssertionStatus;
     public final Name equals;
     public final Name error;
-    public final Name family;
     public final Name finalize;
-    public final Name forName;
     public final Name forRemoval;
     public final Name getClass;
-    public final Name getClassLoader;
-    public final Name getComponentType;
-    public final Name getDeclaringClass;
-    public final Name getMessage;
     public final Name hasNext;
     public final Name hashCode;
     public final Name init;
-    public final Name initCause;
     public final Name iterator;
     public final Name length;
     public final Name next;
@@ -114,12 +102,10 @@
 
     // class names
     public final Name java_io_Serializable;
-    public final Name java_lang_AutoCloseable;
     public final Name java_lang_Class;
     public final Name java_lang_Cloneable;
     public final Name java_lang_Enum;
     public final Name java_lang_Object;
-    public final Name java_lang_invoke_MethodHandle;
 
     // names of builtin classes
     public final Name Array;
@@ -189,7 +175,6 @@
 
     // other identifiers
     public final Name T;
-    public final Name deprecated;
     public final Name ex;
     public final Name module_info;
     public final Name package_info;
@@ -217,14 +202,10 @@
         empty = fromString("");
         hyphen = fromString("-");
         one = fromString("1");
-        period = fromString(".");
-        semicolon = fromString(";");
         slash = fromString("/");
-        slashequals = fromString("/=");
 
         // keywords
         _class = fromString("class");
-        _default = fromString("default");
         _super = fromString("super");
         _this = fromString("this");
         var = fromString("var");
@@ -247,24 +228,16 @@
         clinit = fromString("<clinit>");
         clone = fromString("clone");
         close = fromString("close");
-        compareTo = fromString("compareTo");
         deserializeLambda = fromString("$deserializeLambda$");
         desiredAssertionStatus = fromString("desiredAssertionStatus");
         equals = fromString("equals");
         error = fromString("<error>");
-        family = fromString("family");
         finalize = fromString("finalize");
-        forName = fromString("forName");
         forRemoval = fromString("forRemoval");
         getClass = fromString("getClass");
-        getClassLoader = fromString("getClassLoader");
-        getComponentType = fromString("getComponentType");
-        getDeclaringClass = fromString("getDeclaringClass");
-        getMessage = fromString("getMessage");
         hasNext = fromString("hasNext");
         hashCode = fromString("hashCode");
         init = fromString("<init>");
-        initCause = fromString("initCause");
         iterator = fromString("iterator");
         length = fromString("length");
         next = fromString("next");
@@ -279,12 +252,10 @@
 
         // class names
         java_io_Serializable = fromString("java.io.Serializable");
-        java_lang_AutoCloseable = fromString("java.lang.AutoCloseable");
         java_lang_Class = fromString("java.lang.Class");
         java_lang_Cloneable = fromString("java.lang.Cloneable");
         java_lang_Enum = fromString("java.lang.Enum");
         java_lang_Object = fromString("java.lang.Object");
-        java_lang_invoke_MethodHandle = fromString("java.lang.invoke.MethodHandle");
 
         // names of builtin classes
         Array = fromString("Array");
@@ -354,7 +325,6 @@
 
         // other identifiers
         T = fromString("T");
-        deprecated = fromString("deprecated");
         ex = fromString("ex");
         module_info = fromString("module-info");
         package_info = fromString("package-info");
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java	Tue Mar 26 09:05:10 2019 -0400
@@ -410,10 +410,10 @@
 
         // DER OID
         byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
-        int keySize = params.getCurve().getField().getFieldSize();
+        int orderLength = params.getOrder().bitLength();
 
-        // seed is twice the key size (in bytes) plus 1
-        byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
+        // seed is twice the order length (in bytes) plus 1
+        byte[] seed = new byte[(((orderLength + 7) >> 3) + 1) * 2];
 
         random.nextBytes(seed);
 
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -660,6 +660,7 @@
     SECItem kGpoint = { siBuffer, NULL, 0};
     int flen = 0;    /* length in bytes of the field size */
     unsigned olen;   /* length in bytes of the base point order */
+    unsigned int orderBitSize;
 
 #if EC_DEBUG
     char mpstr[256];
@@ -762,10 +763,11 @@
     SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */
 
     /* In the definition of EC signing, digests are truncated
-     * to the length of n in bits.
+     * to the order length
      * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
-    if (digest->len*8 > (unsigned int)ecParams->fieldID.size) {
-        mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
+    orderBitSize = mpl_significant_bits(&n);
+    if (digest->len*8 > orderBitSize) {
+        mpl_rsh(&s,&s,digest->len*8 - orderBitSize);
     }
 
 #if EC_DEBUG
@@ -898,6 +900,7 @@
     int slen;       /* length in bytes of a half signature (r or s) */
     int flen;       /* length in bytes of the field size */
     unsigned olen;  /* length in bytes of the base point order */
+    unsigned int orderBitSize;
 
 #if EC_DEBUG
     char mpstr[256];
@@ -977,11 +980,12 @@
     SECITEM_TO_MPINT(*digest, &u1);                  /* u1 = HASH(M)     */
 
     /* In the definition of EC signing, digests are truncated
-     * to the length of n in bits.
+     * to the order length, in bits.
      * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
     /* u1 = HASH(M')     */
-    if (digest->len*8 > (unsigned int)ecParams->fieldID.size) {
-        mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size);
+    orderBitSize = mpl_significant_bits(&n);
+    if (digest->len*8 > orderBitSize) {
+        mpl_rsh(&u1,&u1,digest->len*8- orderBitSize);
     }
 
 #if EC_DEBUG
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeCache.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeCache.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,6 @@
 
 public class CodeCache {
   private static GrowableArray<CodeHeap> heapArray;
-  private static AddressField scavengeRootNMethodsField;
   private static VirtualConstructor virtualConstructor;
 
   static {
@@ -56,8 +55,6 @@
     AddressField heapsField = type.getAddressField("_heaps");
     heapArray = GrowableArray.create(heapsField.getValue(), heapConstructor);
 
-    scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods");
-
     virtualConstructor = new VirtualConstructor(db);
     // Add mappings for all possible CodeBlob subclasses
     virtualConstructor.addMapping("BufferBlob", BufferBlob.class);
@@ -73,10 +70,6 @@
     }
   }
 
-  public NMethod scavengeRootMethods() {
-    return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootNMethodsField.getValue());
-  }
-
   public boolean contains(Address p) {
     for (int i = 0; i < heapArray.length(); ++i) {
       if (heapArray.at(i).contains(p)) {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java	Tue Mar 26 09:05:10 2019 -0400
@@ -38,8 +38,6 @@
   private static CIntegerField entryBCIField;
   /** To support simple linked-list chaining of nmethods */
   private static AddressField  osrLinkField;
-  private static AddressField  scavengeRootLinkField;
-  private static JByteField    scavengeRootStateField;
 
   /** Offsets for different nmethod parts */
   private static CIntegerField exceptionOffsetField;
@@ -88,8 +86,6 @@
 
     entryBCIField               = type.getCIntegerField("_entry_bci");
     osrLinkField                = type.getAddressField("_osr_link");
-    scavengeRootLinkField       = type.getAddressField("_scavenge_root_link");
-    scavengeRootStateField      = type.getJByteField("_scavenge_root_state");
 
     exceptionOffsetField        = type.getCIntegerField("_exception_offset");
     origPCOffsetField           = type.getCIntegerField("_orig_pc_offset");
@@ -251,14 +247,6 @@
     return (NMethod) VMObjectFactory.newObject(NMethod.class, osrLinkField.getValue(addr));
   }
 
-  public NMethod getScavengeRootLink() {
-    return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootLinkField.getValue(addr));
-  }
-
-  public int getScavengeRootState() {
-    return (int) scavengeRootStateField.getValue(addr);
-  }
-
   // MethodHandle
   public boolean isMethodHandleReturn(Address returnPc) {
     // Hard to read a bit fields from Java and it's only there for performance
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZHeap.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/z/ZHeap.java	Tue Mar 26 09:05:10 2019 -0400
@@ -48,7 +48,7 @@
         Type type = db.lookupType("ZHeap");
 
         pageAllocatorFieldOffset = type.getAddressField("_page_allocator").getOffset();
-        pageTableFieldOffset = type.getAddressField("_pagetable").getOffset();
+        pageTableFieldOffset = type.getAddressField("_page_table").getOffset();
     }
 
     public ZHeap(Address addr) {
--- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java	Tue Mar 26 09:05:10 2019 -0400
@@ -43,7 +43,7 @@
  * <ol><li>{@link #getRequestMethod()} to determine the command
  * <li>{@link #getRequestHeaders()} to examine the request headers (if needed)
  * <li>{@link #getRequestBody()} returns a {@link java.io.InputStream} for reading the request body.
- *     After reading the request body, the stream is close.
+ *     After reading the request body, the stream should be closed.
  * <li>{@link #getResponseHeaders()} to set any response headers, except content-length
  * <li>{@link #sendResponseHeaders(int,long)} to send the response headers. Must be called before
  * next step.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerStampShiftTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.graalvm.compiler.core.test;
+
+import org.junit.Test;
+
+public class IntegerStampShiftTest extends GraalCompilerTest {
+
+    public static int unsignedShiftPositiveInt(boolean f) {
+        int h = f ? 0x7FFFFFF0 : 0x7FFFFF00;
+        return h >>> 8;
+    }
+
+    @Test
+    public void testUnsignedShiftPositiveInt() {
+        test("unsignedShiftPositiveInt", false);
+    }
+
+    public static int unsignedShiftNegativeInt(boolean f) {
+        int h = f ? 0xFFFFFFF0 : 0xFFFFFF00;
+        return h >>> 8;
+    }
+
+    @Test
+    public void testUnsignedShiftNegativeInt() {
+        test("unsignedShiftNegativeInt", false);
+    }
+
+    public static long unsignedShiftPositiveLong(boolean f) {
+        long h = f ? 0x7FFFFFFFFFFFFFF0L : 0x7FFFFFFFFFFFFF00L;
+        return h >>> 8;
+    }
+
+    @Test
+    public void testUnsignedShiftPositiveLong() {
+        test("unsignedShiftPositiveLong", false);
+    }
+
+    public static long unsignedShiftNegativeLong(boolean f) {
+        long h = f ? 0xFFFFFFFFFFFFFFF0L : 0xFFFFFFFFFFFFFF00L;
+        return h >>> 8;
+    }
+
+    @Test
+    public void testUnsignedShiftNegativeLong() {
+        test("unsignedShiftNegativeLong", false);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Tue Mar 26 09:05:10 2019 -0400
@@ -25,7 +25,7 @@
 package org.graalvm.compiler.core;
 
 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
 import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
@@ -45,14 +45,13 @@
 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
 import org.graalvm.compiler.debug.PathUtilities;
 import org.graalvm.compiler.debug.TTY;
-import org.graalvm.compiler.options.EnumOptionKey;
 import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.code.BailoutException;
 
 /**
  * Wrapper for a compilation that centralizes what action to take based on
- * {@link GraalCompilerOptions#CompilationBailoutAction} and
+ * {@link GraalCompilerOptions#CompilationBailoutAsFailure} and
  * {@link GraalCompilerOptions#CompilationFailureAction} when an uncaught exception occurs during
  * compilation.
  */
@@ -71,14 +70,17 @@
          * Print nothing to the console.
          */
         Silent,
+
         /**
          * Print a stack trace to the console.
          */
         Print,
+
         /**
          * An exception causes the compilation to be retried with extra diagnostics enabled.
          */
         Diagnose,
+
         /**
          * Same as {@link #Diagnose} except that the VM process is exited after retrying.
          */
@@ -122,27 +124,30 @@
     protected abstract T handleException(Throwable t);
 
     /**
-     * Gets the action to take based on the value of {@code actionKey} in {@code options}.
+     * Gets the action to take based on the value of
+     * {@link GraalCompilerOptions#CompilationBailoutAsFailure},
+     * {@link GraalCompilerOptions#CompilationFailureAction} and
+     * {@link GraalCompilerOptions#ExitVMOnException} in {@code options}.
      *
-     * Subclasses can override this to choose a different action based on factors such as whether
-     * {@code actionKey} has been explicitly set in {@code options} for example.
+     * Subclasses can override this to choose a different action.
      *
      * @param cause the cause of the bailout or failure
      */
-    protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
-        if (actionKey == CompilationFailureAction) {
-            if (ExitVMOnException.getValue(options)) {
-                assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
-                assert ExitVMOnException.getDefaultValue() != true;
-                if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
-                    TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
-                                    CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
-                                    ExitVMOnException.getName());
-                }
-                return ExceptionAction.ExitVM;
+    protected ExceptionAction lookupAction(OptionValues options, Throwable cause) {
+        if (cause instanceof BailoutException && !CompilationBailoutAsFailure.getValue(options)) {
+            return ExceptionAction.Silent;
+        }
+        if (ExitVMOnException.getValue(options)) {
+            assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
+            assert ExitVMOnException.getDefaultValue() != true;
+            if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
+                TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
+                                CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
+                                ExitVMOnException.getName());
             }
+            return ExceptionAction.ExitVM;
         }
-        return actionKey.getValue(options);
+        return CompilationFailureAction.getValue(options);
     }
 
     /**
@@ -173,15 +178,6 @@
         } catch (Throwable cause) {
             OptionValues initialOptions = initialDebug.getOptions();
 
-            String causeType = "failure";
-            EnumOptionKey<ExceptionAction> actionKey;
-            if (cause instanceof BailoutException) {
-                actionKey = CompilationBailoutAction;
-                causeType = "bailout";
-            } else {
-                actionKey = CompilationFailureAction;
-                causeType = "failure";
-            }
             synchronized (CompilationFailureAction) {
                 // Serialize all compilation failure handling.
                 // This prevents retry compilation storms and interleaving
@@ -191,9 +187,9 @@
                 // forced crash (i.e., use of GraalCompilerOptions.CrashAt)
                 // is truncated.
 
-                ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
+                ExceptionAction action = lookupAction(initialOptions, cause);
 
-                action = adjustAction(initialOptions, actionKey, action);
+                action = adjustAction(initialOptions, action);
 
                 if (action == ExceptionAction.Silent) {
                     return handleException(cause);
@@ -204,16 +200,14 @@
                     try (PrintStream ps = new PrintStream(baos)) {
                         ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
                         cause.printStackTrace(ps);
-                        ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
-                                        causeType,
-                                        actionKey.getName(), ExceptionAction.Silent,
-                                        actionKey.getName(), ExceptionAction.Silent);
-                        ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
+                        ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+                                        CompilationFailureAction.getName(), ExceptionAction.Silent,
+                                        CompilationFailureAction.getName(), ExceptionAction.Silent);
+                        ps.printf("To capture more information for diagnosing or reporting a compilation failure, " +
                                         "set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
-                                        causeType,
-                                        actionKey.getName(), ExceptionAction.Diagnose,
+                                        CompilationFailureAction.getName(), ExceptionAction.Diagnose,
                                         ExceptionAction.ExitVM,
-                                        actionKey.getName(), ExceptionAction.Diagnose);
+                                        CompilationFailureAction.getName(), ExceptionAction.Diagnose);
                     }
                     TTY.print(baos.toString());
                     return handleException(cause);
@@ -249,15 +243,13 @@
                 try (PrintStream ps = new PrintStream(baos)) {
                     ps.printf("%s: Compilation of %s failed:%n", Thread.currentThread(), this);
                     cause.printStackTrace(ps);
-                    ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
-                                    causeType,
-                                    actionKey.getName(), ExceptionAction.Silent,
-                                    actionKey.getName(), ExceptionAction.Silent);
-                    ps.printf("To print a message for a compilation %s without retrying the compilation, " +
+                    ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+                                    CompilationFailureAction.getName(), ExceptionAction.Silent,
+                                    CompilationFailureAction.getName(), ExceptionAction.Silent);
+                    ps.printf("To print a message for a compilation failure without retrying the compilation, " +
                                     "set %s to %s (e.g., -Dgraal.%s=%s).%n",
-                                    causeType,
-                                    actionKey.getName(), ExceptionAction.Print,
-                                    actionKey.getName(), ExceptionAction.Print);
+                                    CompilationFailureAction.getName(), ExceptionAction.Print,
+                                    CompilationFailureAction.getName(), ExceptionAction.Print);
                     if (dumpPath != null) {
                         ps.println("Retrying compilation of " + this);
                     } else {
@@ -320,7 +312,7 @@
      * Adjusts {@code initialAction} if necessary based on
      * {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
      */
-    private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
+    private ExceptionAction adjustAction(OptionValues initialOptions, ExceptionAction initialAction) {
         ExceptionAction action = initialAction;
         int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
         if (action != ExceptionAction.ExitVM) {
@@ -329,7 +321,7 @@
                     int problems = problemsHandledPerAction.getOrDefault(action, 0);
                     if (problems >= maxProblems) {
                         if (problems == maxProblems) {
-                            TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(),
+                            TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", CompilationFailureAction, action, action.quieter(),
                                             MaxCompilationProblemsPerAction, maxProblems);
                             // Ensure that the message above is only printed once
                             problemsHandledPerAction.put(action, problems + 1);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Tue Mar 26 09:05:10 2019 -0400
@@ -44,13 +44,12 @@
                    "suffix will raise a bailout exception and a ':PermanentBailout' " +
                    "suffix will raise a permanent bailout exception.", type = OptionType.Debug)
     public static final OptionKey<String> CrashAt = new OptionKey<>(null);
-    @Option(help = "file:doc-files/CompilationBailoutActionHelp.txt", type = OptionType.User)
-    public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent);
-    @Option(help = "Specifies the action to take when compilation fails with a bailout exception. " +
-                   "The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
-     public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose);
-    @Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " +
-                   "by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action. " +
+    @Option(help = "Treat compilation bailouts like compilation failures.", type = OptionType.User)
+    public static final OptionKey<Boolean> CompilationBailoutAsFailure = new OptionKey<>(false);
+    @Option(help = "file:doc-files/CompilationFailureActionHelp.txt", type = OptionType.User)
+    public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Silent);
+    @Option(help = "The maximum number of compilation failures to handle with the action specified " +
+                   "by CompilationFailureAction before changing to a less verbose action. " +
                    "This does not apply to the ExitVM action.", type = OptionType.User)
     public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(2);
     @Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationBailoutActionHelp.txt	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-Specifies the action to take when compilation fails with a bailout exception.
-The accepted values are:
-    Silent - Print nothing to the console.
-     Print - Print a stack trace to the console.
-  Diagnose - Retry the compilation with extra diagnostics.
-    ExitVM - Same as Diagnose except that the VM process exits after retrying.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationFailureActionHelp.txt	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,6 @@
+Specifies the action to take when compilation fails.
+The accepted values are:
+    Silent - Print nothing to the console.
+     Print - Print a stack trace to the console.
+  Diagnose - Retry the compilation with extra diagnostics.
+    ExitVM - Same as Diagnose except that the VM process exits after retrying.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayEqualsStub.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.hotspot.amd64;
+
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.hotspot.stubs.SnippetStub;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
+import jdk.internal.vm.compiler.word.Pointer;
+
+import jdk.vm.ci.meta.JavaKind;
+
+public final class AMD64ArrayEqualsStub extends SnippetStub {
+
+    public static final ForeignCallDescriptor STUB_BOOLEAN_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "booleanArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_BYTE_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "byteArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_CHAR_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "charArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_SHORT_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "shortArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_INT_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "intArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_LONG_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "longArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_FLOAT_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "floatArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_DOUBLE_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "doubleArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+
+    public AMD64ArrayEqualsStub(ForeignCallDescriptor foreignCallDescriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
+        super(foreignCallDescriptor.getName(), options, providers, linkage);
+    }
+
+    @Snippet
+    private static boolean booleanArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Boolean);
+    }
+
+    @Snippet
+    private static boolean byteArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Byte);
+    }
+
+    @Snippet
+    private static boolean charArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Char);
+    }
+
+    @Snippet
+    private static boolean shortArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Short);
+    }
+
+    @Snippet
+    private static boolean intArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Int);
+    }
+
+    @Snippet
+    private static boolean longArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Long);
+    }
+
+    @Snippet
+    private static boolean floatArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Float);
+    }
+
+    @Snippet
+    private static boolean doubleArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Double);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Mar 26 09:05:10 2019 -0400
@@ -25,6 +25,7 @@
 package org.graalvm.compiler.hotspot.amd64;
 
 import static jdk.vm.ci.common.InitTimer.timer;
+import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -160,7 +161,7 @@
                     HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
                     HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
         Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
-        AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false);
+        AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9);
         return plugins;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -121,6 +121,22 @@
         link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, options, providers,
                         registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
 
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
         super.initialize(providers, options);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -676,4 +676,32 @@
     protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) {
         return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp);
     }
+
+    @Override
+    public ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
+        if (constantLength >= 0 && constantLength * kind.getByteCount() < 2 * getMaxVectorSize()) {
+            // Yield constant-length arrays comparison assembly
+            return null;
+        }
+        switch (kind) {
+            case Boolean:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS);
+            case Byte:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS);
+            case Char:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS);
+            case Short:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS);
+            case Int:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS);
+            case Long:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS);
+            case Float:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS);
+            case Double:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS);
+            default:
+                return null;
+        }
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,8 +26,6 @@
 
 import static org.junit.Assume.assumeFalse;
 
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.hotspot.replacements.StringUTF16Substitutions;
 import org.graalvm.compiler.nodes.StructuredGraph;
@@ -35,9 +33,11 @@
 import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
 import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
 import org.graalvm.compiler.test.AddExports;
-import org.junit.Before;
 import org.junit.Test;
 
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
 /**
  * Test substitutions for (innate) methods StringUTF16.toBytes and StringUTF16.getChars provided by
  * {@link StringUTF16Substitutions}.
@@ -48,8 +48,7 @@
     private static final int N = 1000;
     private static final int N_OVERFLOW = 10;
 
-    @Before
-    public void checkAMD64() {
+    public StringUTF16ToBytesGetCharsTest() {
         assumeFalse(Java8OrEarlier);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -21,6 +21,8 @@
  * questions.
  */
 
+
+
 package org.graalvm.compiler.hotspot.test;
 
 import java.lang.reflect.InvocationTargetException;
@@ -193,8 +195,7 @@
         Object invokeCode(Object... args) {
             try {
                 return testcode.executeVarargs(args);
-            }
-            catch (InvalidInstalledCodeException e) {
+            } catch (InvalidInstalledCodeException e) {
                 // Ensure the installed code is valid, possibly recompiled.
                 testcode = getCode(testmethod);
 
@@ -208,8 +209,7 @@
         private Object invokeSafe(ResolvedJavaMethod method, Object receiver, Object... args) {
             try {
                 return invoke(method, receiver, args);
-            } catch (IllegalAccessException   | InvocationTargetException |
-                     IllegalArgumentException | InstantiationException e) {
+            } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException | InstantiationException e) {
                 throw new RuntimeException(e);
             }
         }
@@ -220,8 +220,7 @@
         private InstalledCode testcode;
     }
 
-    private static GraalHotSpotVMConfig config =
-        ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig();
+    private static GraalHotSpotVMConfig config = ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig();
 
     private static BigInteger bigTwo = BigInteger.valueOf(2);
     private static Random rnd = new Random(17);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,7 +26,7 @@
 
 import static java.util.Collections.singletonList;
 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Print;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
 import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
@@ -215,7 +215,7 @@
         compilationOptionsCopy.putAll(compilationOptions);
 
         // We want to see stack traces when a method fails to compile
-        CompilationBailoutAction.putIfAbsent(compilationOptionsCopy, Print);
+        CompilationBailoutAsFailure.putIfAbsent(compilationOptionsCopy, true);
         CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print);
 
         // By default only report statistics for the CTW threads themselves
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.test;
 
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
@@ -44,7 +44,7 @@
 
     @Test
     public void testJDK() throws Throwable {
-        ExceptionAction originalBailoutAction = CompilationBailoutAction.getValue(getInitialOptions());
+        boolean originalBailoutAction = CompilationBailoutAsFailure.getValue(getInitialOptions());
         ExceptionAction originalFailureAction = CompilationFailureAction.getValue(getInitialOptions());
         // Compile a couple classes in rt.jar
         HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
@@ -52,7 +52,7 @@
         OptionValues initialOptions = getInitialOptions();
         EconomicMap<OptionKey<?>, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false");
         new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile();
-        assert CompilationBailoutAction.getValue(initialOptions) == originalBailoutAction;
+        assert CompilationBailoutAsFailure.getValue(initialOptions) == originalBailoutAction;
         assert CompilationFailureAction.getValue(initialOptions) == originalFailureAction;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java	Tue Mar 26 09:05:10 2019 -0400
@@ -31,7 +31,6 @@
 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
 import org.graalvm.compiler.bytecode.BytecodeStream;
 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
-import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.GraalCompilerOptions;
 import org.graalvm.compiler.core.target.Backend;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
@@ -134,8 +133,8 @@
         OptionValues goptions = options;
         // Silence diagnostics for permanent bailout errors as they
         // are expected for some OSR tests.
-        if (!GraalCompilerOptions.CompilationBailoutAction.hasBeenSet(options)) {
-            goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAction, ExceptionAction.Silent);
+        if (!GraalCompilerOptions.CompilationBailoutAsFailure.hasBeenSet(options)) {
+            goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAsFailure, false);
         }
         // ensure eager resolving
         StructuredGraph graph = parseEager(method, AllowAssumptions.YES, goptions);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,7 +26,7 @@
 
 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Diagnose;
 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
@@ -47,7 +47,6 @@
 import org.graalvm.compiler.debug.DebugDumpScope;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.TimerKey;
-import org.graalvm.compiler.options.EnumOptionKey;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
@@ -145,25 +144,34 @@
         }
 
         @Override
-        protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
-            // Respect current action if it has been explicitly set.
-            if (!actionKey.hasBeenSet(values)) {
-                if (actionKey == CompilationFailureAction) {
-                    // Automatically exit on non-bailout during bootstrap
-                    // or when assertions are enabled.
-                    if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
-                        return ExitVM;
-                    }
-                } else if (actionKey == CompilationBailoutAction && ((BailoutException) cause).isPermanent()) {
-                    // Get more info for permanent bailouts during bootstrap
-                    // or when assertions are enabled.
-                    assert CompilationBailoutAction.getDefaultValue() == ExceptionAction.Silent;
-                    if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
-                        return Diagnose;
+        protected ExceptionAction lookupAction(OptionValues values, Throwable cause) {
+            if (cause instanceof BailoutException) {
+                BailoutException bailout = (BailoutException) cause;
+                if (bailout.isPermanent()) {
+                    // Respect current action if it has been explicitly set.
+                    if (!CompilationBailoutAsFailure.hasBeenSet(values)) {
+                        // Get more info for permanent bailouts during bootstrap
+                        // or when assertions are enabled.
+                        if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+                            return Diagnose;
+                        }
+
                     }
                 }
+                if (!CompilationBailoutAsFailure.getValue(values)) {
+                    return super.lookupAction(values, cause);
+                }
             }
-            return super.lookupAction(values, actionKey, cause);
+
+            // Respect current action if it has been explicitly set.
+            if (!CompilationFailureAction.hasBeenSet(values)) {
+                // Automatically exit on failure during bootstrap
+                // or when assertions are enabled.
+                if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+                    return ExitVM;
+                }
+            }
+            return super.lookupAction(values, cause);
         }
 
         @SuppressWarnings("try")
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java	Tue Mar 26 09:05:10 2019 -0400
@@ -41,6 +41,7 @@
 
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.services.Services;
 
 /**
  * The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The
@@ -89,15 +90,14 @@
     }
 
     /**
-     * Global options. The values for these options are initialized by parsing the file denoted by
-     * the {@code VM.getSavedProperty(String) saved} system property named
-     * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists followed by parsing the options
-     * encoded in saved system properties whose names start with
-     * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned
-     * file with {@link Properties#load(java.io.Reader)}.
+     * Gets and parses options based on {@linkplain Services#getSavedProperties() saved system
+     * properties}. The values for these options are initialized by parsing the file denoted by the
+     * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} property followed by parsing the options encoded
+     * in properties whose names start with {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs
+     * are parsed from the aforementioned file with {@link Properties#load(java.io.Reader)}.
      */
     @SuppressWarnings("try")
-    private static OptionValues initializeOptions() {
+    public static EconomicMap<OptionKey<?>, Object> parseOptions() {
         EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
         try (InitTimer t = timer("InitializeOptions")) {
 
@@ -142,7 +142,17 @@
             }
 
             OptionsParser.parseOptions(optionSettings, values, loader);
-            return new OptionValues(values);
+            return values;
         }
     }
+
+    /**
+     * Substituted by
+     * {@code com.oracle.svm.graal.hotspot.libgraal.Target_org_graalvm_compiler_hotspot_HotSpotGraalOptionValues}
+     * to update {@code com.oracle.svm.core.option.RuntimeOptionValues.singleton()} instead of
+     * creating a new {@link OptionValues} object.
+     */
+    private static OptionValues initializeOptions() {
+        return new OptionValues(parseOptions());
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -269,6 +269,11 @@
     Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers);
 
     @SuppressWarnings("unused")
+    default ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
+        return null;
+    }
+
+    @SuppressWarnings("unused")
     default Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
         throw GraalError.unimplemented("Array.equals with different types substitution is not implemented on this architecture");
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.nodes.calc;
 
+import jdk.vm.ci.code.CodeUtil;
 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.UShr;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
@@ -84,10 +85,13 @@
             Stamp xStampGeneric = forX.stamp(view);
             if (xStampGeneric instanceof IntegerStamp) {
                 IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+                long xMask = CodeUtil.mask(xStamp.getBits());
+                long xLowerBound = xStamp.lowerBound() & xMask;
+                long xUpperBound = xStamp.upperBound() & xMask;
 
-                if (xStamp.lowerBound() >>> amount == xStamp.upperBound() >>> amount) {
+                if (xLowerBound >>> amount == xUpperBound >>> amount) {
                     // The result of the shift is constant.
-                    return ConstantNode.forIntegerKind(stamp.getStackKind(), xStamp.lowerBound() >>> amount);
+                    return ConstantNode.forIntegerKind(stamp.getStackKind(), xLowerBound >>> amount);
                 }
 
                 if (amount == xStamp.getBits() - 1 && xStamp.lowerBound() == -1 && xStamp.upperBound() == 0) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java	Tue Mar 26 09:05:10 2019 -0400
@@ -32,7 +32,6 @@
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
 import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java11OrEarlier;
 import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
 
@@ -71,7 +70,7 @@
 
 public class AMD64GraphBuilderPlugins {
 
-    public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks) {
+    public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks, boolean emitJDK9StringSubstitutions) {
         InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
         invocationPlugins.defer(new Runnable() {
             @Override
@@ -83,8 +82,10 @@
                                 new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object, JavaKind.Boolean, JavaKind.Byte, JavaKind.Short, JavaKind.Char, JavaKind.Float, JavaKind.Double});
                 registerUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, explicitUnsafeNullChecks);
                 registerStringPlugins(invocationPlugins, replacementsBytecodeProvider);
-                registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
-                registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
+                if (emitJDK9StringSubstitutions) {
+                    registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
+                    registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
+                }
                 registerMathPlugins(invocationPlugins, arch, replacementsBytecodeProvider);
                 registerArraysEqualsPlugins(invocationPlugins, replacementsBytecodeProvider);
             }
@@ -215,30 +216,26 @@
     }
 
     private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
-            r.setAllowOverwrite(true);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class);
-        }
+        Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
+        r.setAllowOverwrite(true);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class);
     }
 
     private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
-            r.setAllowOverwrite(true);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", char[].class, int.class, byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class);
-        }
+        Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
+        r.setAllowOverwrite(true);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", char[].class, int.class, byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class);
     }
 
     private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider, boolean explicitUnsafeNullChecks) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,14 @@
 
 import static org.graalvm.compiler.nodeinfo.InputType.Memory;
 
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.spi.Canonicalizable;
 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodeinfo.NodeCycles;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodeinfo.NodeSize;
@@ -48,11 +51,14 @@
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.Value;
 
 // JaCoCo Exclude
@@ -63,6 +69,13 @@
 @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = NodeSize.SIZE_128)
 public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
 
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Use Array equals stubs instead of embedding all the emitted code.")
+        public static final OptionKey<Boolean> ArrayEqualsStubs = new OptionKey<>(true);
+        // @formatter:on
+    }
+
     public static final NodeClass<ArrayEqualsNode> TYPE = NodeClass.create(ArrayEqualsNode.class);
     /** {@link JavaKind} of the arrays to compare. */
     protected final JavaKind kind;
@@ -178,7 +191,7 @@
     }
 
     @NodeIntrinsic
-    static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
+    public static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
 
     public static boolean equals(boolean[] array1, boolean[] array2, int length) {
         return equals(array1, array2, length, JavaKind.Boolean);
@@ -214,11 +227,25 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
+        LIRGeneratorTool tool = gen.getLIRGeneratorTool();
         int constantLength = -1;
         if (length.isConstant()) {
             constantLength = length.asJavaConstant().asInt();
         }
-        Value result = gen.getLIRGeneratorTool().emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false);
+
+        if (Options.ArrayEqualsStubs.getValue(graph().getOptions())) {
+            ResolvedJavaMethod method = graph().method();
+            if (method != null && method.getAnnotation(Snippet.class) == null) {
+                ForeignCallLinkage linkage = tool.lookupArrayEqualsStub(kind, constantLength);
+                if (linkage != null) {
+                    Value result = tool.emitForeignCall(linkage, null, gen.operand(array1), gen.operand(array2), gen.operand(length));
+                    gen.setResult(this, result);
+                    return;
+                }
+            }
+        }
+
+        Value result = tool.emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false);
         gen.setResult(this, result);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTag.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTag.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -85,6 +85,7 @@
     SUB(BlockType.INLINE, EndTag.END),
     TABLE,
     TBODY,
+    THEAD,
     TD,
     TH,
     TITLE(BlockType.OTHER, EndTag.END),
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Table.java	Tue Mar 26 09:05:10 2019 -0400
@@ -190,7 +190,6 @@
      *
      * <p>Notes:
      * <ul>
-     * <li>This currently does not use a {@code <thead>} tag, but probably should, eventually
      * <li>The column styles are not currently applied to the header, but probably should, eventually
      * </ul>
      *
@@ -450,7 +449,9 @@
 
     private Content getTableBody() {
         ContentBuilder tableContent = new ContentBuilder();
-        tableContent.add(header.toContent());
+        Content thead = new HtmlTree(HtmlTag.THEAD);
+        thead.add(header.toContent());
+        tableContent.add(thead);
         Content tbody = new HtmlTree(HtmlTag.TBODY);
         bodyRows.forEach(row -> tbody.add(row));
         tableContent.add(tbody);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Tue Mar 26 09:05:10 2019 -0400
@@ -837,39 +837,47 @@
         tagletManager = tagletManager == null ?
                 new TagletManager(nosince, showversion, showauthor, javafx, this) :
                 tagletManager;
-        for (List<String> args : customTagStrs) {
-            if (args.get(0).equals("-taglet")) {
-                tagletManager.addCustomTag(args.get(1), getFileManager(), tagletpath);
-                continue;
+        JavaFileManager fileManager = getFileManager();
+        Messages messages = getMessages();
+        try {
+            tagletManager.initTagletPath(fileManager, tagletpath);
+            tagletManager.loadTaglets(fileManager);
+
+            for (List<String> args : customTagStrs) {
+                if (args.get(0).equals("-taglet")) {
+                    tagletManager.addCustomTag(args.get(1), fileManager);
+                    continue;
+                }
+                List<String> tokens = tokenize(args.get(1), TagletManager.SIMPLE_TAGLET_OPT_SEPARATOR, 3);
+                switch (tokens.size()) {
+                    case 1:
+                        String tagName = args.get(1);
+                        if (tagletManager.isKnownCustomTag(tagName)) {
+                            //reorder a standard tag
+                            tagletManager.addNewSimpleCustomTag(tagName, null, "");
+                        } else {
+                            //Create a simple tag with the heading that has the same name as the tag.
+                            StringBuilder heading = new StringBuilder(tagName + ":");
+                            heading.setCharAt(0, Character.toUpperCase(tagName.charAt(0)));
+                            tagletManager.addNewSimpleCustomTag(tagName, heading.toString(), "a");
+                        }
+                        break;
+
+                    case 2:
+                        //Add simple taglet without heading, probably to excluding it in the output.
+                        tagletManager.addNewSimpleCustomTag(tokens.get(0), tokens.get(1), "");
+                        break;
+
+                    case 3:
+                        tagletManager.addNewSimpleCustomTag(tokens.get(0), tokens.get(2), tokens.get(1));
+                        break;
+
+                    default:
+                        messages.error("doclet.Error_invalid_custom_tag_argument", args.get(1));
+                }
             }
-            List<String> tokens = tokenize(args.get(1), TagletManager.SIMPLE_TAGLET_OPT_SEPARATOR, 3);
-            switch (tokens.size()) {
-                case 1:
-                    String tagName = args.get(1);
-                    if (tagletManager.isKnownCustomTag(tagName)) {
-                        //reorder a standard tag
-                        tagletManager.addNewSimpleCustomTag(tagName, null, "");
-                    } else {
-                        //Create a simple tag with the heading that has the same name as the tag.
-                        StringBuilder heading = new StringBuilder(tagName + ":");
-                        heading.setCharAt(0, Character.toUpperCase(tagName.charAt(0)));
-                        tagletManager.addNewSimpleCustomTag(tagName, heading.toString(), "a");
-                    }
-                    break;
-
-                case 2:
-                    //Add simple taglet without heading, probably to excluding it in the output.
-                    tagletManager.addNewSimpleCustomTag(tokens.get(0), tokens.get(1), "");
-                    break;
-
-                case 3:
-                    tagletManager.addNewSimpleCustomTag(tokens.get(0), tokens.get(2), tokens.get(1));
-                    break;
-
-                default:
-                    Messages messages = getMessages();
-                    messages.error("doclet.Error_invalid_custom_tag_argument", args.get(1));
-            }
+        } catch (IOException e) {
+            messages.error("doclet.taglet_could_not_set_location", e.toString());
         }
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -141,8 +141,6 @@
 
         JavacTask t = BasicJavacTask.instance(toolEnv.context);
         doclint = new DocLint();
-        // standard doclet normally generates H1, H2
-        doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2");
         doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);
     }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Tue Mar 26 09:05:10 2019 -0400
@@ -56,6 +56,8 @@
 doclet.Notice_taglet_conflict_warn=Note: Custom tags that could override future standard tags: {0}. To avoid potential overrides, use at least one period character (.) in custom tag names.
 doclet.Error_taglet_not_registered=Error - Exception {0} thrown while trying to register Taglet {1}...
 doclet.Error_invalid_custom_tag_argument=Error - {0} is an invalid argument to the -tag option...
+doclet.taglet_could_not_set_location = Could not set the taglet path: {0}
+doclet.not_standard_file_manager = Cannot set taglet path; the file manager is not a StandardJavaFileManager
 doclet.Author=Author:
 doclet.DefaultValue=Default value:
 doclet.PropertyDescription=Property description:
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java	Tue Mar 26 09:05:10 2019 -0400
@@ -204,45 +204,78 @@
     }
 
     /**
-     * Add a new {@code Taglet}.  Print a message to indicate whether or not
+     * Initializes the location TAGLET_PATH which is used to locate the custom taglets.
+     * @param fileManager the filemanager to load classes and resources.
+     * @param tagletPath the path to the custom taglet.
+     * @throws IOException if an error occurs while setting the location.
+     */
+    public void initTagletPath(JavaFileManager fileManager, String tagletPath) throws IOException {
+        if (fileManager instanceof StandardJavaFileManager) {
+            StandardJavaFileManager sfm = (StandardJavaFileManager)fileManager;
+            if (tagletPath != null) {
+                List<File> paths = new ArrayList<>();
+                for (String pathname : tagletPath.split(File.pathSeparator)) {
+                    paths.add(new File(pathname));
+                }
+                sfm.setLocation(TAGLET_PATH, paths);
+            } else if (!sfm.hasLocation(TAGLET_PATH)) {
+                sfm.setLocation(TAGLET_PATH, Collections.emptyList());
+            }
+        } else if (tagletPath != null) {
+            messages.error("doclet.not_standard_file_manager");
+        }
+    }
+
+    /**
+     * Adds a new {@code Taglet}.  Print a message to indicate whether or not
      * the Taglet was registered properly.
      * @param classname  the name of the class representing the custom tag.
      * @param fileManager the filemanager to load classes and resources.
-     * @param tagletPath  the path to the class representing the custom tag.
      */
-    public void addCustomTag(String classname, JavaFileManager fileManager, String tagletPath) {
+    public void addCustomTag(String classname, JavaFileManager fileManager) {
         try {
             ClassLoader tagClassLoader;
-            if (!fileManager.hasLocation(TAGLET_PATH)) {
-                List<File> paths = new ArrayList<>();
-                if (tagletPath != null) {
-                    for (String pathname : tagletPath.split(File.pathSeparator)) {
-                        paths.add(new File(pathname));
-                    }
-                }
-                if (fileManager instanceof StandardJavaFileManager) {
-                    ((StandardJavaFileManager) fileManager).setLocation(TAGLET_PATH, paths);
-                }
-            }
             tagClassLoader = fileManager.getClassLoader(TAGLET_PATH);
             Class<? extends jdk.javadoc.doclet.Taglet> customTagClass =
                     tagClassLoader.loadClass(classname).asSubclass(jdk.javadoc.doclet.Taglet.class);
             jdk.javadoc.doclet.Taglet instance = customTagClass.getConstructor().newInstance();
-            instance.init(docEnv, doclet);
-            Taglet newLegacy = new UserTaglet(instance);
-            String tname = newLegacy.getName();
-            Taglet t = allTaglets.get(tname);
-            if (t != null) {
-                allTaglets.remove(tname);
+            registerTaglet(instance);
+        } catch (ReflectiveOperationException exc) {
+            messages.error("doclet.Error_taglet_not_registered", exc.getClass().getName(),
+                    classname);
+        }
+    }
+
+    /**
+     * Loads taglets from a taglet path using service loader.
+     * @param fileManager the filemanager to load the taglets.
+     * @throws IOException if an error occurs while getting the service loader.
+     */
+    public void loadTaglets(JavaFileManager fileManager) throws IOException {
+        Iterable<? extends File> location = ((StandardJavaFileManager)fileManager).getLocation(TAGLET_PATH);
+        if (location != null && location.iterator().hasNext()) {
+            ServiceLoader<jdk.javadoc.doclet.Taglet> serviceLoader =
+                    fileManager.getServiceLoader(TAGLET_PATH, jdk.javadoc.doclet.Taglet.class);
+            Iterator<jdk.javadoc.doclet.Taglet> iterator = serviceLoader.iterator();
+            while (iterator.hasNext()) {
+                jdk.javadoc.doclet.Taglet taglet = iterator.next();
+                registerTaglet(taglet);
             }
-            allTaglets.put(tname, newLegacy);
-            messages.notice("doclet.Notice_taglet_registered", classname);
-        } catch (Exception exc) {
-            messages.error("doclet.Error_taglet_not_registered", exc.getClass().getName(), classname);
         }
     }
 
     /**
+     * Registers the {@code Taglet}. Prints a message if a {@code Taglet} got registered properly.
+     * @param instance the {@code Taglet} instance.
+     */
+    private void registerTaglet(jdk.javadoc.doclet.Taglet instance) {
+        instance.init(docEnv, doclet);
+        Taglet newLegacy = new UserTaglet(instance);
+        allTaglets.put(newLegacy.getName(), newLegacy);
+        messages.notice("doclet.Notice_taglet_registered", instance.getClass().getName());
+    }
+
+    /**
      * Add a new {@code SimpleTaglet}.  If this tag already exists
      * and the header passed as an argument is null, move tag to the back of the
      * list. If this tag already exists and the header passed as an argument is
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -33,10 +33,11 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.TreeSet;
+import java.util.Set;
 
 import com.sun.jdi.BooleanType;
 import com.sun.jdi.BooleanValue;
@@ -110,7 +111,7 @@
     // tested unsynchronized (since once true, it stays true), but must
     // be set synchronously
     private Map<Long, ReferenceType> typesByID;
-    private TreeSet<ReferenceType> typesBySignature;
+    private Set<ReferenceType> typesBySignature;
     private boolean retrievedAllTypes = false;
 
     private Map<Long, ModuleReference> modulesByID;
@@ -843,14 +844,9 @@
                 throw new InternalException("Invalid reference type tag");
         }
 
-        /*
-         * If a signature was specified, make sure to set it ASAP, to
-         * prevent any needless JDWP command to retrieve it. (for example,
-         * typesBySignature.add needs the signature, to maintain proper
-         * ordering.
-         */
-        if (signature != null) {
-            type.setSignature(signature);
+        if (signature == null && retrievedAllTypes) {
+            // do not cache if signature is not provided
+            return type;
         }
 
         typesByID.put(id, type);
@@ -920,7 +916,7 @@
 
     private void initReferenceTypes() {
         typesByID = new HashMap<>(300);
-        typesBySignature = new TreeSet<>();
+        typesBySignature = new HashSet<>();
     }
 
     ReferenceTypeImpl referenceType(long ref, byte tag) {
@@ -969,6 +965,9 @@
                 if (retType == null) {
                     retType = addReferenceType(id, tag, signature);
                 }
+                if (signature != null) {
+                    retType.setSignature(signature);
+                }
             }
             return retType;
         }
--- a/src/jdk.jdwp.agent/unix/native/libjdwp/linker_md.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.jdwp.agent/unix/native/libjdwp/linker_md.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,16 +24,8 @@
  */
 
 /*
- * Adapted from JDK 1.2 linker_md.c v1.37. Note that we #define
- * NATIVE here, whether or not we're running solaris native threads.
- * Outside the VM, it's unclear how we can do the locking that is
- * done in the green threads version of the code below.
- */
-#define NATIVE
-
-/*
  * Machine Dependent implementation of the dynamic linking support
- * for java.  This routine is Solaris specific.
+ * for java.  This routine is Unix specific.
  */
 
 #include <stdio.h>
@@ -43,10 +35,6 @@
 #include <string.h>
 
 #include "path_md.h"
-#ifndef NATIVE
-#include "iomgr.h"
-#include "threads_md.h"
-#endif
 
 #ifdef __APPLE__
 #define LIB_SUFFIX "dylib"
@@ -85,7 +73,7 @@
 int
 dbgsysBuildFunName(char *name, int nameLen, int args_size, int encodingIndex)
 {
-  /* On Solaris, there is only one encoding method. */
+    // On Unix, there is only one encoding method.
     if (encodingIndex == 0)
         return 1;
     return 0;
@@ -96,12 +84,13 @@
  * appropriate pre and extensions to a filename and the path
  */
 void
-dbgsysBuildLibName(char *holder, int holderlen, const char *pname, const char *fname)
+dbgsysBuildLibName(char *holder, int holderlen, const char *pname,
+                   const char *fname)
 {
     const int pnamelen = pname ? strlen(pname) : 0;
 
     *holder = '\0';
-    /* Quietly truncate on buffer overflow.  Should be an error. */
+    // Quietly truncate on buffer overflow.  Should be an error.
     if (pnamelen + (int)strlen(fname) + 10 > holderlen) {
         return;
     }
@@ -113,30 +102,11 @@
     }
 }
 
-#ifndef NATIVE
-extern int thr_main(void);
-#endif
-
 void *
 dbgsysLoadLibrary(const char *name, char *err_buf, int err_buflen)
 {
     void * result;
-#ifdef NATIVE
     result = dlopen(name, RTLD_LAZY);
-#else
-    sysMonitorEnter(greenThreadSelf(), &_dl_lock);
-    result = dlopen(name, RTLD_NOW);
-    sysMonitorExit(greenThreadSelf(), &_dl_lock);
-    /*
-     * This is a bit of bulletproofing to catch the commonly occurring
-     * problem of people loading a library which depends on libthread into
-     * the VM.  thr_main() should always return -1 which means that libthread
-     * isn't loaded.
-     */
-    if (thr_main() != -1) {
-         VM_CALL(panic)("libthread loaded into green threads");
-    }
-#endif
     if (result == NULL) {
         (void)strncpy(err_buf, dlerror(), err_buflen-2);
         err_buf[err_buflen-1] = '\0';
@@ -146,24 +116,10 @@
 
 void dbgsysUnloadLibrary(void *handle)
 {
-#ifndef NATIVE
-    sysMonitorEnter(greenThreadSelf(), &_dl_lock);
-#endif
     (void)dlclose(handle);
-#ifndef NATIVE
-    sysMonitorExit(greenThreadSelf(), &_dl_lock);
-#endif
 }
 
 void * dbgsysFindLibraryEntry(void *handle, const char *name)
 {
-    void * sym;
-#ifndef NATIVE
-    sysMonitorEnter(greenThreadSelf(), &_dl_lock);
-#endif
-    sym =  dlsym(handle, name);
-#ifndef NATIVE
-    sysMonitorExit(greenThreadSelf(), &_dl_lock);
-#endif
-    return sym;
+    return dlsym(handle, name);
 }
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketInputStreamInstrumentor.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketInputStreamInstrumentor.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,15 +27,14 @@
 
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Socket;
 
 import jdk.jfr.events.SocketReadEvent;
 
 /**
  * See {@link JITracer} for an explanation of this code.
  */
-@JIInstrumentationTarget("java.net.SocketInputStream")
-@JITypeMapping(from = "jdk.jfr.internal.instrument.SocketInputStreamInstrumentor$AbstractPlainSocketImpl",
-            to = "java.net.AbstractPlainSocketImpl")
+@JIInstrumentationTarget("java.net.Socket$SocketInputStream")
 final class SocketInputStreamInstrumentor {
 
     private SocketInputStreamInstrumentor() {
@@ -43,30 +42,28 @@
 
     @SuppressWarnings("deprecation")
     @JIInstrumentationMethod
-    int read(byte b[], int off, int length, int timeout) throws IOException {
+    public int read(byte b[], int off, int length) throws IOException {
         SocketReadEvent event = SocketReadEvent.EVENT.get();
         if (!event.isEnabled()) {
-            return read(b, off, length, timeout);
+            return read(b, off, length);
         }
         int bytesRead = 0;
         try {
             event.begin();
-            bytesRead = read(b, off, length, timeout);
+            bytesRead = read(b, off, length);
         } finally {
             event.end();
             if (event.shouldCommit()) {
-                String hostString  = impl.address.toString();
-                int delimiterIndex = hostString.lastIndexOf('/');
-
-                event.host      = hostString.substring(0, delimiterIndex);
-                event.address   = hostString.substring(delimiterIndex + 1);
-                event.port      = impl.port;
+                InetAddress remote = parent.getInetAddress();
+                event.host = remote.getHostName();
+                event.address = remote.getHostAddress();
+                event.port = parent.getPort();
                 if (bytesRead < 0) {
                     event.endOfStream = true;
                 } else {
                     event.bytesRead = bytesRead;
                 }
-                event.timeout   = timeout;
+                event.timeout = parent.getSoTimeout();
 
                 event.commit();
                 event.reset();
@@ -75,14 +72,6 @@
         return bytesRead;
     }
 
-    private AbstractPlainSocketImpl impl = null;
-
-    void silenceFindBugsUnwrittenField(InetAddress dummy) {
-        impl.address = dummy;
-    }
-
-    static class AbstractPlainSocketImpl {
-        InetAddress address;
-        int port;
-    }
+    // private field in java.net.Socket$SocketInputStream
+    private Socket parent;
 }
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketOutputStreamInstrumentor.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/SocketOutputStreamInstrumentor.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,15 +27,14 @@
 
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.Socket;
 
 import jdk.jfr.events.SocketWriteEvent;
 
 /**
  * See {@link JITracer} for an explanation of this code.
  */
-@JIInstrumentationTarget("java.net.SocketOutputStream")
-@JITypeMapping(from = "jdk.jfr.internal.instrument.SocketOutputStreamInstrumentor$AbstractPlainSocketImpl",
-            to = "java.net.AbstractPlainSocketImpl")
+@JIInstrumentationTarget("java.net.Socket$SocketOutputStream")
 final class SocketOutputStreamInstrumentor {
 
     private SocketOutputStreamInstrumentor() {
@@ -43,27 +42,25 @@
 
     @SuppressWarnings("deprecation")
     @JIInstrumentationMethod
-    private void socketWrite(byte b[], int off, int len) throws IOException {
+    public void write(byte b[], int off, int len) throws IOException {
         SocketWriteEvent event = SocketWriteEvent.EVENT.get();
         if (!event.isEnabled()) {
-            socketWrite(b, off, len);
+            write(b, off, len);
             return;
         }
         int bytesWritten = 0;
         try {
             event.begin();
-            socketWrite(b, off, len);
+            write(b, off, len);
             bytesWritten = len;
         } finally {
             event.end() ;
             if (event.shouldCommit()) {
-                String hostString  = impl.address.toString();
-                int delimiterIndex = hostString.lastIndexOf('/');
-
-                event.host         = hostString.substring(0, delimiterIndex);
-                event.address      = hostString.substring(delimiterIndex + 1);
-                event.port         = impl.port;
-                event.bytesWritten = bytesWritten < 0 ? 0 : bytesWritten;
+                InetAddress remote = parent.getInetAddress();
+                event.host = remote.getHostName();
+                event.address = remote.getHostAddress();
+                event.port = parent.getPort();
+                event.bytesWritten = bytesWritten;
 
                 event.commit();
                 event.reset();
@@ -71,14 +68,6 @@
         }
     }
 
-    private AbstractPlainSocketImpl impl = null;
-
-    void silenceFindBugsUnwrittenField(InetAddress dummy) {
-        impl.address = dummy;
-    }
-
-    static class AbstractPlainSocketImpl {
-        InetAddress address;
-        int port;
-    }
+    // private field in java.net.Socket$SocketOutputStream
+    private Socket parent;
 }
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Command.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -243,7 +243,7 @@
             }
             rad.read(); // try to read 1 byte
         } catch (FileNotFoundException e) {
-            throw new UserDataException("could not find file '" + path + "'");
+            throw new UserDataException("could not open file " + e.getMessage());
         } catch (IOException e) {
             throw new UserDataException("i/o error reading file '" + path + "', " + e.getMessage());
         }
--- a/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,13 +45,14 @@
     private static Registry registry;
     private static int port = -1;
     private static boolean startRegistry = true;
+    private static RemoteHost remoteHost;
 
     private static void printUsage() {
         System.err.println("usage: jstatd [-nr] [-p port] [-n rminame]\n" +
                            "       jstatd -?|-h|--help");
     }
 
-    static void bind(String name, RemoteHostImpl remoteHost)
+    static void bind(String name, RemoteHost remoteHost)
                 throws RemoteException, MalformedURLException, Exception {
 
         try {
@@ -138,10 +139,10 @@
         try {
             // use 1.5.0 dynamically generated subs.
             System.setProperty("java.rmi.server.ignoreSubClasses", "true");
-            RemoteHostImpl remoteHost = new RemoteHostImpl();
+            remoteHost = new RemoteHostImpl();
             RemoteHost stub = (RemoteHost) UnicastRemoteObject.exportObject(
                     remoteHost, 0);
-            bind(name.toString(), remoteHost);
+            bind(name.toString(), stub);
             System.out.println("jstatd started (bound to " + name.toString() + ")");
             System.out.flush();
         } catch (MalformedURLException e) {
--- a/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,7 @@
 
     private MonitoredHost monitoredHost;
     private Set<Integer> activeVms;
+    private static RemoteVm rvm;
 
     public RemoteHostImpl() throws MonitorException {
         try {
@@ -76,7 +77,7 @@
         try {
             VmIdentifier vmid = new VmIdentifier(vmidStr);
             MonitoredVm mvm = monitoredHost.getMonitoredVm(vmid);
-            RemoteVmImpl rvm = new RemoteVmImpl((BufferedMonitoredVm)mvm);
+            rvm = new RemoteVmImpl((BufferedMonitoredVm)mvm);
             stub = (RemoteVm) UnicastRemoteObject.exportObject(rvm, 0);
         }
         catch (URISyntaxException e) {
--- a/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.net/linux/classes/jdk/net/LinuxSocketOptions.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 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
--- a/src/jdk.net/macosx/classes/jdk/net/MacOSXSocketOptions.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.net/macosx/classes/jdk/net/MacOSXSocketOptions.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+ * 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
--- a/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.net/macosx/native/libextnet/MacOSXSocketOptions.c	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+ * 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
--- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -465,7 +465,7 @@
                     if (state != ChannelState.PENDING)
                         throw new NoConnectionPendingException();
                 }
-                int n = 0;
+                boolean connected = false;
                 try {
                     try {
                         begin();
@@ -477,26 +477,11 @@
                                 receiverThread = NativeThread.current();
                             }
                             if (!isBlocking()) {
-                                for (;;) {
-                                    n = Net.pollConnect(fd, 0);
-                                    if (  (n == IOStatus.INTERRUPTED)
-                                          && isOpen())
-                                        continue;
-                                    break;
-                                }
+                                connected = Net.pollConnect(fd, 0);
                             } else {
-                                for (;;) {
-                                    n = Net.pollConnect(fd, -1);
-                                    if (n == 0) {
-                                        // Loop in case of
-                                        // spurious notifications
-                                        continue;
-                                    }
-                                    if (  (n == IOStatus.INTERRUPTED)
-                                          && isOpen())
-                                        continue;
-                                    break;
-                                }
+                                do {
+                                    connected = Net.pollConnect(fd, -1);
+                                } while (!connected && isOpen());
                             }
                         }
                     } finally {
@@ -504,16 +489,10 @@
                             receiverThread = 0;
                             if (state == ChannelState.KILLPENDING) {
                                 kill();
-                                /* poll()/getsockopt() does not report
-                                 * error (throws exception, with n = 0)
-                                 * on Linux platform after dup2 and
-                                 * signal-wakeup. Force n to 0 so the
-                                 * end() can throw appropriate exception */
-                                n = 0;
+                                connected = false;
                             }
                         }
-                        end((n > 0) || (n == IOStatus.UNAVAILABLE));
-                        assert IOStatus.check(n);
+                        end(connected);
                     }
                 } catch (IOException x) {
                     /* If an exception was thrown, close the channel after
@@ -523,7 +502,7 @@
                     throw x;
                 }
 
-                if (n > 0) {
+                if (connected) {
                     synchronized (stateLock) {
                         state = ChannelState.CONNECTED;
                         if (!isBound()) {
--- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -230,7 +230,7 @@
                     return null;
                 thread = NativeThread.current();
                 for (;;) {
-                    n = accept0(fd, newfd, isaa);
+                    n = Net.accept(fd, newfd, isaa);
                     if ((n == IOStatus.INTERRUPTED) && isOpen())
                         continue;
                     break;
@@ -412,22 +412,4 @@
             return SctpNet.getLocalAddresses(fdVal);
         }
     }
-
-    /* Native */
-    private static native void initIDs();
-
-    private static native int accept0(FileDescriptor ssfd,
-        FileDescriptor newfd, InetSocketAddress[] isaa) throws IOException;
-
-    static {
-        IOUtil.load();   // loads nio & net native libraries
-        java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Void>() {
-                public Void run() {
-                    System.loadLibrary("sctp");
-                    return null;
-                }
-            });
-        initIDs();
-    }
 }
--- a/src/jdk.sctp/unix/native/libsctp/SctpServerChannelImpl.c	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, 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 "sun_nio_ch_sctp_SctpServerChannelImpl.h"
-
-extern void Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(JNIEnv* env,
-    jclass c);
-
-extern jint Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv* env,
-    jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa);
-
-/*
- * Class:     sun_nio_ch_sctp_SctpServerChannelImpl
- * Method:    initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_nio_ch_sctp_SctpServerChannelImpl_initIDs
-  (JNIEnv* env, jclass c) {
-    Java_sun_nio_ch_ServerSocketChannelImpl_initIDs(env, c);
-}
-
-/*
- * Class:     sun_nio_ch_sctp_SctpServerChannelImpl
- * Method:    accept0
- * Signature: (Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;[Ljava/net/InetSocketAddress;)I
- */
-JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpServerChannelImpl_accept0
-  (JNIEnv* env, jobject this, jobject ssfdo, jobject newfdo, jobjectArray isaa) {
-    return Java_sun_nio_ch_ServerSocketChannelImpl_accept0(env, this,
-                                                           ssfdo, newfdo, isaa);
-}
--- a/src/utils/hsdis/Makefile	Tue Mar 26 08:57:28 2019 -0400
+++ b/src/utils/hsdis/Makefile	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # The Universal Permissive License (UPL), Version 1.0
@@ -201,6 +201,10 @@
 		$(TARGET_DIR)/opcodes/libopcodes.a \
 		$(TARGET_DIR)/libiberty/libiberty.a
 
+ifneq ($(MINGW),)
+LIBRARIES +=	$(TARGET_DIR)/zlib/libz.a
+endif
+
 DEMO_TARGET	= $(TARGET_DIR)/hsdis-demo
 DEMO_SOURCE	= hsdis-demo.c
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/gtest/gc/z/test_zForwarding.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zPage.inline.hpp"
+#include "unittest.hpp"
+
+using namespace testing;
+
+#define CAPTURE_DELIM "\n"
+#define CAPTURE1(expression) #expression << " evaluates to " << expression
+#define CAPTURE2(e0, e1)                 CAPTURE1(e0) << CAPTURE_DELIM << CAPTURE1(e1)
+
+#define CAPTURE(expression) CAPTURE1(expression)
+
+class ZForwardingTest : public Test {
+public:
+  // Helper functions
+
+  static bool is_power_of_2(uint32_t value) {
+    return ::is_power_of_2((intptr_t)value);
+  }
+
+  class SequenceToFromIndex : AllStatic {
+  public:
+    static uintptr_t even(uint32_t sequence_number) {
+      return sequence_number * 2;
+    }
+    static uintptr_t odd(uint32_t sequence_number) {
+      return even(sequence_number) + 1;
+    }
+    static uintptr_t one_to_one(uint32_t sequence_number) {
+      return sequence_number;
+    }
+  };
+
+  // Test functions
+
+  static void setup(ZForwarding* forwarding) {
+    EXPECT_PRED1(is_power_of_2, forwarding->_entries.length()) << CAPTURE(forwarding->_entries.length());
+  }
+
+  static void find_empty(ZForwarding* forwarding) {
+    uint32_t size = forwarding->_entries.length();
+    uint32_t entries_to_check = size * 2;
+
+    for (uint32_t i = 0; i < entries_to_check; i++) {
+      uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+      EXPECT_TRUE(forwarding->find(from_index).is_empty()) << CAPTURE2(from_index, size);
+    }
+
+    EXPECT_TRUE(forwarding->find(uintptr_t(-1)).is_empty()) << CAPTURE(size);
+  }
+
+  static void find_full(ZForwarding* forwarding) {
+    uint32_t size = forwarding->_entries.length();
+    uint32_t entries_to_populate = size;
+
+    // Populate
+    for (uint32_t i = 0; i < entries_to_populate; i++) {
+      uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+      ZForwardingCursor cursor;
+      ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+      ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+      forwarding->insert(from_index, from_index, &cursor);
+    }
+
+    // Verify
+    for (uint32_t i = 0; i < entries_to_populate; i++) {
+      uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+      ZForwardingEntry entry = forwarding->find(from_index);
+      ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+      ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
+      ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
+    }
+  }
+
+  static void find_every_other(ZForwarding* forwarding) {
+    uint32_t size = forwarding->_entries.length();
+    uint32_t entries_to_populate = size / 2;
+
+    // Populate even from indices
+    for (uint32_t i = 0; i < entries_to_populate; i++) {
+      uintptr_t from_index = SequenceToFromIndex::even(i);
+
+      ZForwardingCursor cursor;
+      ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+      ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+      forwarding->insert(from_index, from_index, &cursor);
+    }
+
+    // Verify populated even indices
+    for (uint32_t i = 0; i < entries_to_populate; i++) {
+      uintptr_t from_index = SequenceToFromIndex::even(i);
+
+      ZForwardingCursor cursor;
+      ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+      ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+      ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
+      ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
+    }
+
+    // Verify empty odd indices
+    //
+    // This check could be done on a larger range of sequence numbers,
+    // but currently entries_to_populate is used.
+    for (uint32_t i = 0; i < entries_to_populate; i++) {
+      uintptr_t from_index = SequenceToFromIndex::odd(i);
+
+      ZForwardingEntry entry = forwarding->find(from_index);
+
+      ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+    }
+  }
+
+  static void test(void (*function)(ZForwarding*), uint32_t size) {
+    // Create page
+    const ZVirtualMemory vmem(0, ZPageSizeSmall);
+    const ZPhysicalMemory pmem(ZPhysicalMemorySegment(0, ZPageSizeSmall));
+    ZPage page(ZPageTypeSmall, vmem, pmem);
+
+    page.reset();
+
+    const size_t object_size = 16;
+    const uintptr_t object = page.alloc_object(object_size);
+
+    ZGlobalSeqNum++;
+
+    bool dummy = false;
+    page.mark_object(ZAddress::marked(object), dummy, dummy);
+
+    const uint32_t live_objects = size;
+    const uint32_t live_bytes = live_objects * object_size;
+    page.inc_live_atomic(live_objects, live_bytes);
+
+    // Setup forwarding
+    ZForwarding* const forwarding = ZForwarding::create(&page);
+
+    // Actual test function
+    (*function)(forwarding);
+
+    // Teardown forwarding
+    ZForwarding::destroy(forwarding);
+
+    // Teardown page
+    page.physical_memory().clear();
+  }
+
+  // Run the given function with a few different input values.
+  static void test(void (*function)(ZForwarding*)) {
+    test(function, 1);
+    test(function, 2);
+    test(function, 3);
+    test(function, 4);
+    test(function, 7);
+    test(function, 8);
+    test(function, 1023);
+    test(function, 1024);
+    test(function, 1025);
+  }
+};
+
+TEST_F(ZForwardingTest, setup) {
+  test(&ZForwardingTest::setup);
+}
+
+TEST_F(ZForwardingTest, find_empty) {
+  test(&ZForwardingTest::find_empty);
+}
+
+TEST_F(ZForwardingTest, find_full) {
+  test(&ZForwardingTest::find_full);
+}
+
+TEST_F(ZForwardingTest, find_every_other) {
+  test(&ZForwardingTest::find_every_other);
+}
--- a/test/hotspot/gtest/gc/z/test_zForwardingTable.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zForwardingTable.inline.hpp"
-#include "unittest.hpp"
-
-using namespace testing;
-
-#define CAPTURE_DELIM "\n"
-#define CAPTURE1(expression) #expression << " evaluates to " << expression
-#define CAPTURE2(e0, e1)                 CAPTURE1(e0) << CAPTURE_DELIM << CAPTURE1(e1)
-
-#define CAPTURE(expression) CAPTURE1(expression)
-
-class ZForwardingTableTest : public Test {
-public:
-  // Helper functions
-
-  static bool is_power_of_2(size_t value) {
-    return ::is_power_of_2((intptr_t)value);
-  }
-
-  class SequenceToFromIndex : AllStatic {
-  public:
-    static uintptr_t even(uint32_t sequence_number) {
-      return sequence_number * 2;
-    }
-    static uintptr_t odd(uint32_t sequence_number) {
-      return even(sequence_number) + 1;
-    }
-    static uintptr_t one_to_one(uint32_t sequence_number) {
-      return sequence_number;
-    }
-  };
-
-  // Test functions
-
-  static void setup(ZForwardingTable& table) {
-    EXPECT_PRED1(is_power_of_2, table._size) << CAPTURE(table._size);
-  }
-
-  static void find_empty(ZForwardingTable& table) {
-    size_t size = table._size;
-    size_t entries_to_check = size * 2;
-
-    for (uint32_t i = 0; i < entries_to_check; i++) {
-      uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
-      EXPECT_TRUE(table.find(from_index).is_empty()) << CAPTURE2(from_index, size);
-    }
-
-    EXPECT_TRUE(table.find(uintptr_t(-1)).is_empty()) << CAPTURE(size);
-  }
-
-  static void find_full(ZForwardingTable& table) {
-    size_t size = table._size;
-    size_t entries_to_populate = size;
-
-    // Populate
-    for (uint32_t i = 0; i < entries_to_populate; i++) {
-      uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
-      ZForwardingTableCursor cursor;
-      ZForwardingTableEntry entry = table.find(from_index, &cursor);
-      ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
-
-      table.insert(from_index, from_index, &cursor);
-    }
-
-    // Verify
-    for (uint32_t i = 0; i < entries_to_populate; i++) {
-      uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
-      ZForwardingTableEntry entry = table.find(from_index);
-      ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
-
-      ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
-      ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
-    }
-  }
-
-  static void find_every_other(ZForwardingTable& table) {
-    size_t size = table._size;
-    size_t entries_to_populate = size / 2;
-
-    // Populate even from indices
-    for (uint32_t i = 0; i < entries_to_populate; i++) {
-      uintptr_t from_index = SequenceToFromIndex::even(i);
-
-      ZForwardingTableCursor cursor;
-      ZForwardingTableEntry entry = table.find(from_index, &cursor);
-      ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
-
-      table.insert(from_index, from_index, &cursor);
-    }
-
-    // Verify populated even indices
-    for (uint32_t i = 0; i < entries_to_populate; i++) {
-      uintptr_t from_index = SequenceToFromIndex::even(i);
-
-      ZForwardingTableCursor cursor;
-      ZForwardingTableEntry entry = table.find(from_index, &cursor);
-      ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
-
-      ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
-      ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
-    }
-
-    // Verify empty odd indices
-    //
-    // This check could be done on a larger range of sequence numbers,
-    // but currently entries_to_populate is used.
-    for (uint32_t i = 0; i < entries_to_populate; i++) {
-      uintptr_t from_index = SequenceToFromIndex::odd(i);
-
-      ZForwardingTableEntry entry = table.find(from_index);
-
-      ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
-    }
-  }
-
-  static void test(void (*function)(ZForwardingTable&), uint32_t size) {
-    // Setup
-    ZForwardingTable table;
-    table.setup(size);
-    ASSERT_FALSE(table.is_null());
-
-    // Actual test function
-    (*function)(table);
-
-    // Teardown
-    table.reset();
-    ASSERT_TRUE(table.is_null());
-  }
-
-  // Run the given function with a few different input values.
-  static void test(void (*function)(ZForwardingTable&)) {
-    test(function, 1);
-    test(function, 2);
-    test(function, 3);
-    test(function, 4);
-    test(function, 7);
-    test(function, 8);
-    test(function, 1023);
-    test(function, 1024);
-    test(function, 1025);
-  }
-};
-
-TEST_F(ZForwardingTableTest, setup) {
-  test(&ZForwardingTableTest::setup);
-}
-
-TEST_F(ZForwardingTableTest, find_empty) {
-  test(&ZForwardingTableTest::find_empty);
-}
-
-TEST_F(ZForwardingTableTest, find_full) {
-  test(&ZForwardingTableTest::find_full);
-}
-
-TEST_F(ZForwardingTableTest, find_every_other) {
-  test(&ZForwardingTableTest::find_every_other);
-}
--- a/test/hotspot/jtreg/ProblemList-graal.txt	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/ProblemList-graal.txt	Tue Mar 26 09:05:10 2019 -0400
@@ -36,6 +36,7 @@
 compiler/compilercontrol/jcmd/AddExcludeTest.java               8181753   generic-all
 compiler/compilercontrol/jcmd/AddLogTest.java                   8181753   generic-all
 compiler/compilercontrol/mixed/RandomValidCommandsTest.java     8181753   generic-all
+compiler/compilercontrol/mixed/RandomCommandsTest.java          8181753   generic-all
 
 compiler/graalunit/JttThreadsTest.java                          8208066   generic-all
 
@@ -205,8 +206,6 @@
 serviceability/tmtools/jstat/GcCapacityTest.java                              8196611 generic-all
 serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorMultiArrayTest.java     8196611 generic-all
 
-runtime/RedefineObject/TestRedefineObject.java                                8218399 generic-all
-
 vmTestbase/gc/lock/jvmti/alloc/jvmtialloclock02/TestDescription.java          8218700 generic-all
 
 vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java                   8218701 generic-all
--- a/test/hotspot/jtreg/ProblemList-zgc.txt	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/ProblemList-zgc.txt	Tue Mar 26 09:05:10 2019 -0400
@@ -27,4 +27,16 @@
 #
 #############################################################################
 
+serviceability/sa/ClhsdbInspect.java                          8220624   generic-all
+serviceability/sa/ClhsdbJdis.java                             8220624   generic-all
+serviceability/sa/ClhsdbJhisto.java                           8220624   generic-all
+serviceability/sa/ClhsdbJstack.java                           8220624   generic-all
+serviceability/sa/ClhsdbPrintAs.java                          8220624   generic-all
+serviceability/sa/ClhsdbPstack.java                           8220624   generic-all
+serviceability/sa/ClhsdbSource.java                           8220624   generic-all
+serviceability/sa/TestClhsdbJstackLock.java                   8220624   generic-all
+serviceability/sa/TestHeapDumpForInvokeDynamic.java           8220624   generic-all
+serviceability/sa/TestHeapDumpForLargeArray.java              8220624   generic-all
+serviceability/sa/TestUniverse.java                           8220624   generic-all
+serviceability/sa/TestJmapCore.java                           8220624   generic-all
 serviceability/sa/TestJmapCoreMetaspace.java                  8219443   generic-all
--- a/test/hotspot/jtreg/ProblemList.txt	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/ProblemList.txt	Tue Mar 26 09:05:10 2019 -0400
@@ -80,9 +80,9 @@
 
 # :hotspot_runtime
 
-runtime/handshake/HandshakeWalkSuspendExitTest.java 8214174 generic-all
 runtime/NMT/CheckForProperDetailStackTrace.java 8218458 generic-all
 runtime/SharedArchiveFile/SASymbolTableTest.java 8193639 solaris-all
+runtime/containers/docker/TestCPUSets.java 8220672 generic-all
 
 #############################################################################
 
@@ -158,7 +158,6 @@
 vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Deadlock/JavaDeadlock001/TestDescription.java 8060733 generic-all
 
 vmTestbase/nsk/jdi/ThreadReference/stop/stop001/TestDescription.java 7034630 generic-all
-vmTestbase/nsk/jdi/EventRequest/setEnabled/setenabled003/TestDescription.java 8066993 generic-all
 vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses021/TestDescription.java 8065773 generic-all
 vmTestbase/nsk/jdi/VirtualMachine/redefineClasses/redefineclasses023/TestDescription.java 8065773 generic-all
 
--- a/test/hotspot/jtreg/TEST.groups	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/TEST.groups	Tue Mar 26 09:05:10 2019 -0400
@@ -281,11 +281,6 @@
  -runtime/modules/ModuleStress/ExportModuleStressTest.java \
  -runtime/modules/ModuleStress/ModuleStressGC.java \
  -runtime/NMT \
- -runtime/RedefineObject/TestRedefineObject.java \
- -runtime/RedefineTests/RedefineLeak.java \
- -runtime/RedefineTests/RedefinePreviousVersions.java \
- -runtime/RedefineTests/RedefineRunningMethods.java \
- -runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java \
  -runtime/ReservedStack \
  -runtime/SelectionResolution/AbstractMethodErrorTest.java \
  -runtime/SelectionResolution/IllegalAccessErrorTest.java \
@@ -329,6 +324,12 @@
 tier1_serviceability = \
   serviceability/dcmd/compiler \
   -serviceability/dcmd/compiler/CompilerQueueTest.java \
+  serviceability/jvmti/RedefineClasses \
+  -serviceability/jvmti/RedefineClasses/RedefineLeak.java \
+  -serviceability/jvmti/RedefineClasses/RedefinePreviousVersions.java \
+  -serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java \
+  -serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithBacktrace.java \
+  -serviceability/jvmti/RedefineClasses/TestRedefineObject.java \
   serviceability/logging \
   serviceability/sa \
   -serviceability/sa/ClhsdbScanOops.java \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileAbsoluteDirectoryTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @requires vm.aot
+ * @library / /test/lib /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.aot.cli.jaotc.CompileAbsoluteDirectoryTest
+ * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
+ *                                compiler.aot.cli.jaotc.data.HelloWorldTwo
+ * @run driver compiler.aot.cli.jaotc.CompileAbsoluteDirectoryTest
+ * @summary check jaotc can compile directory with classes where directory is specified by absolute path
+ * @bug 8218859
+ */
+package compiler.aot.cli.jaotc;
+
+import compiler.aot.cli.jaotc.data.HelloWorldOne;
+import compiler.aot.cli.jaotc.data.HelloWorldTwo;
+import java.io.File;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class CompileAbsoluteDirectoryTest {
+    public static void main(String[] args) {
+        try {
+            String dir = new java.io.File(".").getAbsolutePath();
+            System.out.println("Do test --directory " + dir);
+            OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--directory", dir);
+            oa.shouldHaveExitValue(0);
+            File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
+            Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
+            Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
+            JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
+            JaotcTestHelper.checkLibraryUsage(HelloWorldTwo.class.getName());
+        } catch (Exception e) {
+            throw new Error("Can't get full path name for '.', got exception " + e, e);
+        }
+    }
+}
--- a/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileDirectoryTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/compiler/aot/cli/jaotc/CompileDirectoryTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
  * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
  *                                compiler.aot.cli.jaotc.data.HelloWorldTwo
  * @run driver compiler.aot.cli.jaotc.CompileDirectoryTest
- * @summary check jaotc can compile directory with classes
+ * @summary check jaotc can compile directory with classes where directory is specified by relative path
  */
 package compiler.aot.cli.jaotc;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/c1/Test8211100.java	Tue Mar 26 09:05:10 2019 -0400
@@ -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.
+ */
+
+/**
+ * @test
+ * @bug 8211100
+ * @summary hotspot C1 issue with comparing long numbers on x86 32-bit
+ *
+ * @run main/othervm -XX:+PrintCompilation -XX:CompileOnly=compiler.c1.Test8211100::test
+ *                   -XX:CompileCommand=quiet compiler.c1.Test8211100
+ */
+
+package compiler.c1;
+
+public class Test8211100 {
+    private static final int ITERATIONS = 100_000;
+
+    public static void main(String[] args) {
+        for (int i = 0; i < ITERATIONS; i++) {
+            test(4558828911L,
+                 4294967296L);
+        }
+    }
+
+    private static void test(long one, long two) {
+        while (true) {
+            if (one >= two) {
+                break;
+            }
+        }
+    }
+}
--- a/test/hotspot/jtreg/compiler/classUnloading/methodUnloading/TestOverloadCompileQueues.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/compiler/classUnloading/methodUnloading/TestOverloadCompileQueues.java	Tue Mar 26 09:05:10 2019 -0400
@@ -25,6 +25,7 @@
  * @test TestOverloadCompileQueues
  * @bug 8163511
  * @summary Test overloading the C1 and C2 compile queues with tasks.
+ * @requires !vm.graal.enabled
  * @run main/othervm -XX:-TieredCompilation -XX:CompileThreshold=2 -XX:CICompilerCount=1
  *                   compiler.classUnloading.methodUnloading.TestOverloadCompileQueues
  * @run main/othervm -XX:TieredCompileTaskTimeout=1000 -XX:CompileThresholdScaling=0.001 -XX:CICompilerCount=2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/codegen/BadLogicCode.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4157675
+ * @summary Solaris JIT generates bad code for logic expression
+ * @author Tom Rodriguez
+ * @run main compiler.codegen.BadLogicCode
+ */
+
+package compiler.codegen;
+
+public class BadLogicCode {
+    static int values[] = {Integer.MIN_VALUE, -1, 0, 1, 4, 16, 31,
+                           32, 33, Integer.MAX_VALUE};
+    static char b[][] = {null, new char[32]};
+    static boolean nullPtr = false, indexOutBnd = false;
+    static boolean indexOutBnd2 = false;
+
+    public static void main(String args[]) throws Exception{
+        int i = 1, j = 4, k = 9;
+
+        nullPtr = (b[i] == null);
+
+        int bufLen = nullPtr ? 0 : b[i].length;
+        indexOutBnd = (values[j] < 0)
+            || (values[j] > bufLen)
+            || (values[k] < 0)
+            || ((values[j] + values[k]) > bufLen)
+            ||((values[j] + values[k]) < 0);
+
+        indexOutBnd2 = (values[j] < 0);
+        indexOutBnd2 = indexOutBnd2 || (values[j] > bufLen);
+        indexOutBnd2 = indexOutBnd2 || (values[k] < 0);
+        indexOutBnd2 = indexOutBnd2 || ((values[j] + values[k]) > bufLen);
+        indexOutBnd2 = indexOutBnd2 ||((values[j] + values[k]) < 0);
+        if (indexOutBnd != indexOutBnd2)
+            throw new Error("logic expression generate different results");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/codegen/ShiftTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4093292
+ * @summary Test for correct code generation by the JIT
+ * @run main compiler.codegen.ShiftTest
+ */
+
+package compiler.codegen;
+
+public class ShiftTest {
+    static final int w = 32;
+
+    private static void doTest(long ct) throws Exception {
+        int S22 = 0xc46cf7c2;
+        int S23 = 0xcfda9162;
+        int S24 = 0xd029aa4c;
+        int S25 = 0x17cf1801;
+        int A = (int)(ct & 0xffffffffL);
+        int B = (int)(ct >>> 32);
+        int x, y;
+        x = B - S25;
+        y = A & (w-1);
+        B = ((x >>> y) | (x << (w-y))) ^ A;
+        x = A - S24;
+        y = B & (w-1);
+        A = ((x >>> y) | (x << (w-y))) ^ B;
+        x = B - S23;
+        y = A & (w-1);
+        B = ((x >>> y) | (x << (w-y))) ^ A;
+        x = A - S22;
+        y = B & (w-1);
+        A = ((x >>> y) | (x << (w-y))) ^ B;
+        String astr = Integer.toHexString(A);
+        String bstr = Integer.toHexString(B);
+        System.err.println("A = " + astr + " B = " + bstr);
+        if ((!astr.equals("dcb38144")) ||
+            (!bstr.equals("1916de73"))) {
+            throw new RuntimeException("Unexpected shift results!");
+        }
+        System.err.println("Test passed");
+    }
+
+    public static void main(String[] args) throws Exception {
+        doTest(0x496def29b74be041L);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/codegen/TestOopCmp.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019 SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8221083
+ * @requires vm.bits == 64 & vm.opt.final.UseCompressedOops == true
+ * @summary On ppc64, C1 erroneously emits a 32-bit compare instruction for oop compares.
+ * @modules java.base/jdk.internal.misc:+open
+ * @library /test/lib /
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                                sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbatch -XX:-UseTLAB -Xmx4m -XX:+UseSerialGC -XX:HeapBaseMinAddress=0x700000000
+ *      -XX:CompileCommand=compileonly,compiler.codegen.TestOopCmp::nullTest
+ *      -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *      compiler.codegen.TestOopCmp
+ * @author volker.simonis@gmail.com
+ */
+
+package compiler.codegen;
+
+import sun.hotspot.WhiteBox;
+
+public class TestOopCmp {
+
+    private static Object nullObj = null;
+
+    public static boolean nullTest(Object o) {
+        if (o == nullObj) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static void main(String args[]) {
+
+        WhiteBox WB = WhiteBox.getWhiteBox();
+
+        // The test is started with -XX:HeapBaseMinAddress=0x700000000 and a
+        // small heap of only 4mb. This works pretty reliable and at least on
+        // Linux/Windows/Solaris we will get a heap starting at 0x700000000.
+        // The test also runs with -XX:+UseSerialGC which means that we'll get
+        // eden starting at 0x700000000.
+        // Calling 'System.gc()' will clean up all the objects from eden, so if
+        // eden starts at 0x700000000 the first allocation right after the
+        // system GC will be allcoated right at address 0x700000000.
+        System.gc();
+        String s = new String("I'm not null!!!");
+        if (WB.getObjectAddress(s) == 0x700000000L) {
+            System.out.println("Got object at address 0x700000000");
+        }
+
+        // We call 'nullTest()' with the newly allocated String object. If it was
+        // allocated at 0x700000000, its 32 least-significant bits will be 0 and a
+        // 32-bit comparison with 'nullObj' (which is 'null') will yield true and
+        // result in a test failure.
+        // If the code generated for 'nullTest()' correctly performs a 64-bit
+        // comparison or if we didn't manage to allcoate 's' at 0x700000000 the
+        // test will always succeed.
+        for (int i = 0; i < 30_000; i++) {
+            if (nullTest(s)) {
+                throw new RuntimeException("Comparing non-null object with null returned 'true'");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/exceptions/ExceptionInInit.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4165973
+ * @summary Attempt to read inaccessible property can produce
+ *          exception of the wrong type.
+ * @author Tom Rodriguez
+ *
+ * @modules java.rmi
+ * @run main compiler.exceptions.ExceptionInInit
+ */
+
+package compiler.exceptions;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+public class ExceptionInInit {
+
+    public static void main(String[] args) {
+
+        Test test = null;
+
+        try {
+            System.setSecurityManager(new java.rmi.RMISecurityManager());
+            Test.showTest();
+        } catch (ExceptionInInitializerError e) {
+        }
+    }
+
+    public static class FooBar {
+        static String test = "test";
+        FooBar(String test) {
+            this.test = test;
+        }
+    }
+
+    public static class Test extends FooBar {
+
+        /*
+         * An AccessControlException is thrown in the static initializer of the
+         * class FooBar. This exception should produce an ExceptionInInitializer
+         * error. Instead it causes a more cryptic ClassNotFound error.
+         *
+         * The following is an excerpt from the output from java.security.debug=all
+         *
+         * access: access denied (java.util.PropertyPermission test.src read)
+         * java.lang.Exception: Stack trace
+         *         at java.lang.Thread.dumpStack(Thread.java:938)
+         *         at java.security.AccessControlContext.checkPermission(AccessControlContext.java:184)
+         *         at java.security.AccessController.checkPermission(AccessController.java:402)
+         *         at java.lang.SecurityManager.checkPermission(SecurityManager.java:516)
+         *         at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1035)
+         *         at java.lang.System.getProperty(System.java:441)
+         *         at sun.security.action.GetPropertyAction.run(GetPropertyAction.java:73)
+         *         at java.security.AccessController.doPrivileged(Native Method)
+         *         at ExceptionInInit$Test.&#60clinit>(ExceptionInInit.java:33)
+         *         at ExceptionInInit.main(ExceptionInInit.java:18)
+         * access: domain that failed ProtectionDomain (file:/tmp/exceptionInInit/<no certificates>)
+         *
+         * The following exception is occurring when this test program tries
+         * to access the test.src property.
+         */
+        private static String test =
+            AccessController.doPrivileged((PrivilegedAction<String>)() -> System.getProperty("test.src", "."));
+
+        Test(String test) {
+            super(test);
+        }
+        public static void showTest() {
+            System.err.println(test);
+        }
+    }
+}
--- a/test/hotspot/jtreg/compiler/gcbarriers/UnsafeIntrinsicsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/compiler/gcbarriers/UnsafeIntrinsicsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
  * @modules java.base/jdk.internal.misc:+open
  * @summary Validate barriers after Unsafe getReference, CAS and swap (GetAndSet)
  * @requires vm.gc.Z & !vm.graal.enabled
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+UnlockDiagnosticVMOptions -XX:+ZUnmapBadViews -XX:ZCollectionInterval=1 -XX:-CreateCoredumpOnCrash -XX:CompileCommand=dontinline,*::mergeImpl* compiler.gcbarriers.UnsafeIntrinsicsTest
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+UnlockDiagnosticVMOptions -XX:+ZVerifyViews -XX:ZCollectionInterval=1 -XX:-CreateCoredumpOnCrash -XX:CompileCommand=dontinline,*::mergeImpl* compiler.gcbarriers.UnsafeIntrinsicsTest
  */
 
 package compiler.gcbarriers;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/loopstripmining/CheckLoopStripMining.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, SAP SE. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8220374
+ * @summary C2: LoopStripMining doesn't strip as expected
+ * @requires vm.compiler2.enabled
+ *
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+SafepointTimeout -XX:+SafepointALot
+ *                   -XX:+AbortVMOnSafepointTimeout -XX:SafepointTimeoutDelay=500 -XX:GuaranteedSafepointInterval=500
+ *                   -XX:-TieredCompilation -XX:+UseCountedLoopSafepoints -XX:LoopStripMiningIter=1000
+ *                   -XX:LoopUnrollLimit=0 -XX:CompileCommand=compileonly,CheckLoopStripMining::test_loop -Xcomp CheckLoopStripMining
+ *
+ */
+
+public class CheckLoopStripMining {
+
+  public static int test_loop(int x) {
+      int sum = 0;
+      if (x != 0) {
+          for (int y = 1; y < Integer.MAX_VALUE; ++y) {
+              if (y % x == 0) ++sum;
+          }
+      }
+      return sum;
+  }
+
+  public static void main(String args[]) {
+    int sum = test_loop(3);
+    System.out.println("sum: " + sum);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/runtime/JITClassInit.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4154887
+ * @summary self-parser test causes JDK 1.2 Beta4K segmentation fault
+ * @author Tom Rodriguez
+ * @run main/othervm compiler.runtime.JITClassInit
+ */
+
+package compiler.runtime;
+
+public class JITClassInit {
+    public static void main(String[] args) {
+        Token t = new Token();
+        new TokenTable();
+    }
+
+}
+
+class TokenTable {
+    public TokenTable() {
+        new TokenTypeIterator(this);
+    }
+
+    public void for_token_type(Token t) {
+        t.keyword_character_class();
+    }
+}
+
+class Token {
+    public Object keyword_character_class() {
+        return new Object();
+    }
+}
+
+class NameOrKeywordToken extends Token {
+    static TokenTable kt = new TokenTable();
+    public Object keyword_character_class() {
+        return new Object();
+    }
+}
+
+class CapKeywordToken extends NameOrKeywordToken {
+    public Object keyword_character_class() {
+        return new Object();
+    }
+};
+
+
+class TokenTypeIterator {
+    public TokenTypeIterator(TokenTable c) {
+        c.for_token_type(new CapKeywordToken());
+        c.for_token_type(new NameOrKeywordToken());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/ArraySize.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4063078
+ * @summary Allocating a ridiculously large array should not crash the VM
+ * @run main/othervm -Xmx128m -Xms32m gc.ArraySize
+ */
+
+package gc;
+
+public class ArraySize {
+
+    public static void main(String[] args) throws Exception {
+        boolean thrown = false;
+        try {
+            byte[] buf = new byte[Integer.MAX_VALUE - 1];
+            System.out.print(buf[0]);
+        } catch (OutOfMemoryError x) {
+            thrown = true;
+        }
+        if (! thrown) {
+            throw new Exception("Didn't throw expected OutOfMemoryError");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/InfiniteList.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4098578
+ * @summary Check if the VM properly throws OutOfMemoryError
+ * @author Sheng Liang
+ * @run main/othervm -Xmx128m gc.InfiniteList
+ */
+
+package gc;
+
+public class InfiniteList {
+    InfiniteList next;
+    long data[] = new long[50000];
+    public static void main(String[] args) throws Exception {
+        InfiniteList p, q;
+        p = new InfiniteList ();
+        p.data[p.data.length -1 ] = 999;
+        try {
+            while (p != null) {
+                q = new InfiniteList ();
+                q.next = p;
+                p = q;
+            }
+            throw new Exception ("OutOfMemoryError not thrown as expected.");
+        } catch (OutOfMemoryError e) {
+            return;
+        }
+    }
+}
--- a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java	Tue Mar 26 09:05:10 2019 -0400
@@ -174,9 +174,9 @@
 
     private static void verifyType(CollectionInfo ci, boolean shouldExist, String pattern) {
         if (shouldExist) {
-            Asserts.assertTrue(ci.containsVerification(pattern), "Missing expected verification for: " + ci.getName());
+            Asserts.assertTrue(ci.containsVerification(pattern), "Missing expected verification pattern " + pattern + " for: " + ci.getName());
         } else {
-            Asserts.assertFalse(ci.containsVerification(pattern), "Found unexpected verification for: " + ci.getName());
+            Asserts.assertFalse(ci.containsVerification(pattern), "Found unexpected verification pattern " + pattern + " for: " + ci.getName());
         }
     }
 
--- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestMaybeNullUnsafeAccess.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestMaybeNullUnsafeAccess.java	Tue Mar 26 09:05:10 2019 -0400
@@ -28,7 +28,12 @@
  * @requires vm.gc.Shenandoah
  * @modules java.base/jdk.internal.misc:+open
  *
- * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:-TieredCompilation TestMaybeNullUnsafeAccess
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:-TieredCompilation
+ *                   TestMaybeNullUnsafeAccess
+ *
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:-TieredCompilation
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
+ *                   TestMaybeNullUnsafeAccess
  *
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestUnsafeOffheapSwap.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. 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 TestUnsafeOffheapSwap
+ * @summary Miscompilation in Unsafe off-heap swap routines
+ * @key gc
+ * @requires vm.gc.Shenandoah
+ * @modules java.base/jdk.internal.misc:+open
+ *
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:-TieredCompilation
+ *                   -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
+ *                   TestUnsafeOffheapSwap
+ */
+
+import java.util.*;
+import jdk.internal.misc.Unsafe;
+
+public class TestUnsafeOffheapSwap {
+
+    static final int SIZE = 10000;
+    static final long SEED = 1;
+
+    static final jdk.internal.misc.Unsafe UNSAFE = Unsafe.getUnsafe();
+    static final int SCALE = UNSAFE.ARRAY_INT_INDEX_SCALE;
+
+    static Memory mem;
+    static int[] arr;
+
+    public static void main(String[] args) throws Exception {
+        // Bug is exposed when memory.addr is not known statically
+        mem = new Memory(SIZE*SCALE);
+        arr = new int[SIZE];
+
+        for (int i = 0; i < 10; i++) {
+            test();
+        }
+    }
+
+    static void test() {
+        Random rnd = new Random(SEED);
+        for (int i = 0; i < SIZE; i++) {
+            int value = rnd.nextInt();
+            mem.setInt(i, value);
+            arr[i] = value;
+        }
+
+        for (int i = 0; i < SIZE; i++) {
+            if (arr[i] != mem.getInt(i)) {
+                throw new IllegalStateException("TESTBUG: Values mismatch before swaps");
+            }
+        }
+
+        for (int i = 1; i < SIZE; i++) {
+            mem.swap(i - 1, i);
+            int tmp = arr[i - 1];
+            arr[i - 1] = arr[i];
+            arr[i] = tmp;
+        }
+
+        for (int i = 0; i < SIZE; i++) {
+            if (arr[i] != mem.getInt(i)) {
+                throw new IllegalStateException("Values mismatch after swaps");
+            }
+        }
+    }
+
+    static class Memory {
+        private final long addr;
+
+        Memory(int size) {
+            addr = UNSAFE.allocateMemory(size);
+        }
+
+        public int getInt(int idx) {
+            return UNSAFE.getInt(addr + idx*SCALE);
+        }
+
+        public void setInt(int idx, int val) {
+            UNSAFE.putInt(addr + idx*SCALE, val);
+        }
+
+        public void swap(int a, int b) {
+            int tmp = getInt(a);
+            setInt(a, getInt(b));
+            setInt(b, tmp);
+        }
+    }
+}
--- a/test/hotspot/jtreg/gc/shenandoah/options/TestLoopMiningArguments.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/gc/shenandoah/options/TestLoopMiningArguments.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
@@ -53,50 +53,6 @@
     }
 
     public static void main(String[] args) throws Exception {
-        testDefaultGC();
-        testShenandoah();
-    }
-
-    public static void testDefaultGC() throws Exception {
-        testWith("Default GC should have CLS enabled, LSM = 1000",
-                true, 1000);
-
-        testWith("Default GC with +CLS should set LSM = 1",
-                true, 1,
-                "-XX:+UseCountedLoopSafepoints"
-        );
-
-        testWith("Default GC with +CLS should not override LSM>1",
-                true, 10,
-                "-XX:LoopStripMiningIter=10",
-                "-XX:+UseCountedLoopSafepoints"
-        );
-
-        testWith("Default GC with +CLS should not override LSM=1",
-                true, 1,
-                "-XX:LoopStripMiningIter=1",
-                "-XX:+UseCountedLoopSafepoints"
-        );
-
-        testWith("Default GC with +CLS should override LSM=0 to 1",
-                true, 1,
-                "-XX:LoopStripMiningIter=0",
-                "-XX:+UseCountedLoopSafepoints"
-        );
-
-        testWith("Default GC with -CLS should set LSM = 0",
-                false, 0,
-                "-XX:-UseCountedLoopSafepoints"
-        );
-
-        testWith("Default GC with -CLS should override LSM to 0",
-                false, 0,
-                "-XX:LoopStripMiningIter=10",
-                "-XX:-UseCountedLoopSafepoints"
-        );
-    }
-
-    public static void testShenandoah() throws Exception {
         testWith("Shenandoah should have CLS and LSM enabled",
                 true, 1000,
                 "-XX:+UnlockExperimentalVMOptions",
--- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@
         {"InitialRAMFraction",        "64"},
         {"TLABStats",                 "false"},
         {"ThreadLocalHandshakes",     "true"},
+        {"AllowJNIEnvProxy",          "true"},
 
         // deprecated alias flags (see also aliased_jvm_flags):
         {"DefaultMaxRAMFraction", "4"},
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ErrorHandling/ExplicitArithmeticCheck.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4221448
+ * @summary Use explicit check for integer arithmetic exception on win32.
+ */
+
+public class ExplicitArithmeticCheck {
+    public static void main(String argv[]) throws Exception {
+        for (int i = 0; i < 64; i++) {
+          boolean result = false;
+          int n;
+          try {
+              n = 0 / 0;
+          } catch (ArithmeticException e) {
+              result = true;
+          }
+          if (result == false) {
+            throw new Error("Failed to throw correct exception!");
+          }
+          result = false;
+          try {
+              n = 0 % 0;
+          } catch (ArithmeticException e) {
+              result = true;
+          }
+          if (result == false) {
+            throw new Error("Failed to throw correct exception!");
+          }
+          try {
+              n = 0x80000000 / -1;
+          } catch (Throwable t) {
+            throw new Error("Failed to throw correct exception!");
+          }
+          if (n != 0x80000000) {
+            throw new Error("Incorrect integer arithmetic ! ");
+          }
+          try {
+              n = 0x80000000 % -1;
+          } catch (Throwable t) {
+            throw new Error("Failed to throw correct exception!");
+          }
+          if (n != 0) {
+            throw new Error("Incorrect integer arithmetic!");
+          }
+        }
+    }
+}
--- a/test/hotspot/jtreg/runtime/RedefineObject/Agent.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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.security.*;
-import java.lang.instrument.*;
-import java.lang.reflect.*;
-
-public class Agent implements ClassFileTransformer {
-    public synchronized byte[] transform(final ClassLoader classLoader,
-                                         final String className,
-                                         Class<?> classBeingRedefined,
-                                         ProtectionDomain protectionDomain,
-                                         byte[] classfileBuffer) {
-        System.out.println("Transforming class " + className);
-        return classfileBuffer;
-    }
-
-    public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
-
-        try {
-            instrumentation.retransformClasses(to_redefine);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-
-    }
-
-    public static void premain(String agentArgs, Instrumentation instrumentation) {
-        Agent transformer = new Agent();
-        instrumentation.addTransformer(transformer, true);
-
-        // Redefine java/lang/Object and java/lang/reflect/Method.invoke and
-        // java/lang/ClassLoader
-        Class object_class = Object.class;
-        redefine(agentArgs, instrumentation, object_class);
-
-        Class method_class = Method.class;
-        redefine(agentArgs, instrumentation, method_class);
-
-        Class loader_class = ClassLoader.class;
-        redefine(agentArgs, instrumentation, loader_class);
-
-        instrumentation.removeTransformer(transformer);
-    }
-
-    public static void main(String[] args) {
-        byte[] ba = new byte[0];
-
-        // If it survives 100 GC's, it's good.
-        for (int i = 0; i < 100 ; i++) {
-            System.gc();
-            ba.clone();
-        }
-        try {
-            // Use java/lang/reflect/Method.invoke to call
-            WalkThroughInvoke a = new WalkThroughInvoke();
-            Class aclass = WalkThroughInvoke.class;
-            Method m = aclass.getMethod("stackWalk");
-            m.invoke(a);
-        } catch (Exception x) {
-            x.printStackTrace();
-        }
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineObject/TestRedefineObject.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- */
-import java.io.PrintWriter;
-
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-/*
- * Test to redefine java/lang/Object and verify that it doesn't crash on vtable
- * call on basic array type.
- * Test to redefine java/lang/ClassLoader and java/lang/reflect/Method to make
- * sure cached versions used afterward are the current version.
- *
- * @test
- * @bug 8005056
- * @bug 8009728
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- *          java.instrument
- *          java.management
- * @build Agent
- * @run driver ClassFileInstaller Agent
- * @run main TestRedefineObject
- * @run main/othervm -javaagent:agent.jar -Xlog:redefine+class+load=debug,redefine+class+timer=info Agent
- */
-public class TestRedefineObject {
-    public static void main(String[] args) throws Exception  {
-
-      PrintWriter pw = new PrintWriter("MANIFEST.MF");
-      pw.println("Premain-Class: Agent");
-      pw.println("Can-Retransform-Classes: true");
-      pw.close();
-
-      ProcessBuilder pb = new ProcessBuilder();
-      pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "Agent.class"});
-      pb.start().waitFor();
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineObject/WalkThroughInvoke.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2013, 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.lang.reflect.*;
-
-public class WalkThroughInvoke {
-  public void stackWalk() {
-      try {
-          Class b = Object.class;
-          SecurityManager sm = new SecurityManager();
-          // Walks the stack with Method.invoke in the stack (which is the
-          // purpose of the test) before it gets an AccessControlException.
-          sm.checkPermission(new RuntimePermission("accessDeclaredMembers"));
-      } catch (java.security.AccessControlException e) {
-          // Ignoring an 'AccessControlException' exception since
-          // it is expected as part of this test.
-      }
-  }
-};
--- a/test/hotspot/jtreg/runtime/RedefineTests/ModifyAnonymous.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * 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
- * 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
- * @library /test/lib
- * @summary Test that retransforming and redefining anonymous classes gets UnmodifiableClassException
- * @modules java.base/jdk.internal.misc
- * @modules java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main ModifyAnonymous buildagent
- * @run main/othervm -javaagent:redefineagent.jar ModifyAnonymous
- */
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.lang.RuntimeException;
-import java.lang.instrument.ClassDefinition;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.security.ProtectionDomain;
-
-import jdk.test.lib.compiler.InMemoryJavaCompiler;
-
-public class ModifyAnonymous {
-
-    public static class LambdaTransformer implements ClassFileTransformer {
-        @Override
-        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
-                                ProtectionDomain protectionDomain, byte[] classfileBuffer)
-        throws IllegalClassFormatException {
-            return null;
-        }
-    }
-
-    static Instrumentation inst = null;
-    static volatile boolean done = false;
-
-    public static void premain(String args, Instrumentation instrumentation) {
-
-        inst = instrumentation;
-        System.out.println("javaagent in da house!");
-        instrumentation.addTransformer(new LambdaTransformer());
-    }
-
-    private static void buildAgent() {
-        try {
-            ClassFileInstaller.main("ModifyAnonymous");
-        } catch (Exception e) {
-            throw new RuntimeException("Could not write agent classfile", e);
-        }
-
-        try {
-            PrintWriter pw = new PrintWriter("MANIFEST.MF");
-            pw.println("Premain-Class: ModifyAnonymous");
-            pw.println("Agent-Class: ModifyAnonymous");
-            pw.println("Can-Retransform-Classes: true");
-            pw.println("Can-Redefine-Classes: true");
-            pw.close();
-        } catch (FileNotFoundException e) {
-            throw new RuntimeException("Could not write manifest file for the agent", e);
-        }
-
-        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
-        if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "ModifyAnonymous.class" })) {
-            throw new RuntimeException("Could not write the agent jar file");
-        }
-    }
-
-    public static class InstanceMethodCallSiteApp {
-
-        public static void test() throws InterruptedException {
-            for (int i = 0; i < 2; i++) {
-                InstanceMethodCallSiteApp app = new InstanceMethodCallSiteApp();
-                Runnable r = app::doWork;   // this creates an anonymous class
-                while (!done) {
-                    r.run();
-                    Thread.sleep(10);
-                }
-            }
-        }
-
-        public void doWork() {
-            System.out.print(".");
-        }
-    }
-
-    static void runTest() {
-        PrintWriter pw;
-        String logName = System.getProperty("test.classes") +
-            File.separator + "loadedClasses.log";
-        // Create a log file to capture the names of the classes in the
-        // allLoadedClasses array. The log file is for assisting in debugging
-        // in case a null class is encountered in the allLoadedClasses array.
-        try {
-            pw = new PrintWriter(new FileOutputStream(
-                new File(logName), true));
-        } catch (FileNotFoundException e) {
-            throw new RuntimeException("Could not write loaded classes to log", e);
-        }
-        while (!done) {
-            Class[] allLoadedClasses = inst.getAllLoadedClasses();
-            int len = allLoadedClasses.length;
-            pw.println("    allLoadedClasses length: " + len);
-            for (int idx = 0; idx < len; idx++) {
-                Class cls = allLoadedClasses[idx];
-                pw.println("    " + idx + " " +
-                    ((cls != null) ? cls.getName() : "null"));
-            }
-            for (int idx = 0; idx < len; idx++) {
-                Class clazz = allLoadedClasses[idx];
-                if (clazz == null) {
-                    pw.flush();
-                    pw.close();
-                    throw new RuntimeException("null class encountered");
-                }
-                final String name = clazz.getName();
-                if (name.contains("$$Lambda$") && name.contains("App")) {
-                    if (inst.isModifiableClass(clazz)) {
-                        pw.flush();
-                        pw.close();
-                        throw new RuntimeException ("Class should not be modifiable");
-                    }
-                    // Try to modify them anyway.
-                    try {
-                        System.out.println("retransform called for " + name);
-                        inst.retransformClasses(clazz);
-                    } catch(java.lang.instrument.UnmodifiableClassException t) {
-                        System.out.println("PASSED: expecting UnmodifiableClassException");
-                        t.printStackTrace();
-                    }
-                    try {
-                        System.out.println("redefine called for " + name);
-                        String newclass = "class Dummy {}";
-                        byte[] bytecode = InMemoryJavaCompiler.compile("Dummy", newclass);
-                        ClassDefinition cld = new ClassDefinition(clazz, bytecode);
-                        inst.redefineClasses(new ClassDefinition[] { cld });
-                    } catch(java.lang.instrument.UnmodifiableClassException t) {
-                        System.out.println("PASSED: expecting UnmodifiableClassException");
-                        t.printStackTrace();
-                    } catch(java.lang.ClassNotFoundException e) {
-                        pw.flush();
-                        pw.close();
-                        throw new RuntimeException ("ClassNotFoundException thrown");
-                    }
-                    done = true;
-                }
-            }
-        }
-        pw.flush();
-        pw.close();
-    }
-
-    public static void main(String argv[]) throws InterruptedException, RuntimeException {
-        if (argv.length == 1 && argv[0].equals("buildagent")) {
-            buildAgent();
-            return;
-        }
-
-        if (inst == null) {
-            throw new RuntimeException("Instrumentation object was null");
-        }
-
-        new Thread() {
-            public void run() {
-                runTest();
-            }
-        }.start();
-
-        // Test that NCDFE is not thrown for anonymous class:
-        // ModifyAnonymous$InstanceMethodCallSiteApp$$Lambda$18
-        try {
-            ModifyAnonymous test = new ModifyAnonymous();
-            InstanceMethodCallSiteApp.test();
-        } catch (NoClassDefFoundError e) {
-            throw new RuntimeException("FAILED: NoClassDefFoundError thrown for " + e.getMessage());
-        }
-        System.out.println("PASSED: NoClassDefFound error not thrown");
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineAddLambdaExpression.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +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 8193524
- * @summary Redefine a class' public static method that contains a lambda expression
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineAddLambdaExpression
- */
-
-interface MathOperation {
-    public int operation(int a, int b);
-}
-
-class B {
-    public static int operate(int a, int b, MathOperation mathOperation) {
-        return mathOperation.operation(a, b);
-    }
-    static int test_math(String p) {
-        MathOperation addition = (int a, int b) -> a + b;
-        return operate(10, 5, addition);
-    }
-}
-
-public class RedefineAddLambdaExpression {
-
-    public static String newB =
-        "class B {" +
-        "    public static int operate(int a, int b, MathOperation mathOperation) {" +
-        "        return mathOperation.operation(a, b);" +
-        "    }" +
-        "    static int test_math(String p) {" +
-        "        MathOperation addition = (int a, int b) -> a + b;" +
-        "        System.out.println(p + \" from class B's test_math method\");" +
-        "        MathOperation subtraction = (int a, int b) -> a - b;" +
-        "        return operate(10, 5, subtraction);" +
-        "    }" +
-        "}";
-
-    public static void main(String[] args) throws Exception {
-        int res = B.test_math("Hello");
-        System.out.println("Result = " + res);
-        if (res != 15) {
-            throw new Error("test_math returned " + res + " expected " + 15);
-        }
-        RedefineClassHelper.redefineClass(B.class, newB);
-
-        res = B.test_math("Hello");
-        if (res != 5)
-            throw new Error("test_math returned " + res + " expected " + 5);
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineAnnotations.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,414 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * @test
- * @library /test/lib
- * @summary Test that type annotations are retained after a retransform
- * @modules java.base/jdk.internal.misc
- * @modules java.base/jdk.internal.org.objectweb.asm
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineAnnotations buildagent
- * @run main/othervm -javaagent:redefineagent.jar RedefineAnnotations
- */
-
-import static jdk.test.lib.Asserts.assertTrue;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.lang.NoSuchFieldException;
-import java.lang.NoSuchMethodException;
-import java.lang.RuntimeException;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.lang.reflect.AnnotatedArrayType;
-import java.lang.reflect.AnnotatedParameterizedType;
-import java.lang.reflect.AnnotatedType;
-import java.lang.reflect.AnnotatedWildcardType;
-import java.lang.reflect.Executable;
-import java.lang.reflect.TypeVariable;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassVisitor;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.FieldVisitor;
-import static jdk.internal.org.objectweb.asm.Opcodes.ASM7;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE_USE)
-@interface TestAnn {
-    String site();
-}
-
-public class RedefineAnnotations {
-    static Instrumentation inst;
-    public static void premain(String agentArgs, Instrumentation inst) {
-        RedefineAnnotations.inst = inst;
-    }
-
-    static class Transformer implements ClassFileTransformer {
-
-        public byte[] asm(ClassLoader loader, String className,
-                Class<?> classBeingRedefined,
-                ProtectionDomain protectionDomain, byte[] classfileBuffer)
-            throws IllegalClassFormatException {
-
-            ClassWriter cw = new ClassWriter(0);
-            ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { };
-            ClassReader cr = new ClassReader(classfileBuffer);
-            cr.accept(cv, 0);
-            return cw.toByteArray();
-        }
-
-        public class ReAddDummyFieldsClassVisitor extends ClassVisitor {
-
-            LinkedList<F> fields = new LinkedList<>();
-
-            public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) {
-                super(api, cv);
-            }
-
-            @Override public FieldVisitor visitField(int access, String name,
-                    String desc, String signature, Object value) {
-                if (name.startsWith("dummy")) {
-                    // Remove dummy field
-                    fields.addLast(new F(access, name, desc, signature, value));
-                    return null;
-                }
-                return cv.visitField(access, name, desc, signature, value);
-            }
-
-            @Override public void visitEnd() {
-                F f;
-                while ((f = fields.pollFirst()) != null) {
-                    // Re-add dummy fields
-                    cv.visitField(f.access, f.name, f.desc, f.signature, f.value);
-                }
-            }
-
-            private class F {
-                private int access;
-                private String name;
-                private String desc;
-                private String signature;
-                private Object value;
-                F(int access, String name, String desc, String signature, Object value) {
-                    this.access = access;
-                    this.name = name;
-                    this.desc = desc;
-                    this.signature = signature;
-                    this.value = value;
-                }
-            }
-        }
-
-        @Override public byte[] transform(ClassLoader loader, String className,
-                Class<?> classBeingRedefined,
-                ProtectionDomain protectionDomain, byte[] classfileBuffer)
-            throws IllegalClassFormatException {
-
-            if (className.contains("TypeAnnotatedTestClass")) {
-                try {
-                    // Here we remove and re-add the dummy fields. This shuffles the constant pool
-                    return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
-                } catch (Throwable e) {
-                    // The retransform native code that called this method does not propagate
-                    // exceptions. Instead of getting an uninformative generic error, catch
-                    // problems here and print it, then exit.
-                    e.printStackTrace();
-                    System.exit(1);
-                }
-            }
-            return null;
-        }
-    }
-
-    private static void buildAgent() {
-        try {
-            ClassFileInstaller.main("RedefineAnnotations");
-        } catch (Exception e) {
-            throw new RuntimeException("Could not write agent classfile", e);
-        }
-
-        try {
-            PrintWriter pw = new PrintWriter("MANIFEST.MF");
-            pw.println("Premain-Class: RedefineAnnotations");
-            pw.println("Agent-Class: RedefineAnnotations");
-            pw.println("Can-Retransform-Classes: true");
-            pw.close();
-        } catch (FileNotFoundException e) {
-            throw new RuntimeException("Could not write manifest file for the agent", e);
-        }
-
-        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
-        if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineAnnotations.class" })) {
-            throw new RuntimeException("Could not write the agent jar file");
-        }
-    }
-
-    public static void main(String argv[]) throws NoSuchFieldException, NoSuchMethodException {
-        if (argv.length == 1 && argv[0].equals("buildagent")) {
-            buildAgent();
-            return;
-        }
-
-        if (inst == null) {
-            throw new RuntimeException("Instrumentation object was null");
-        }
-
-        RedefineAnnotations test = new RedefineAnnotations();
-        test.testTransformAndVerify();
-    }
-
-    // Class type annotations
-    private Annotation classTypeParameterTA;
-    private Annotation extendsTA;
-    private Annotation implementsTA;
-
-    // Field type annotations
-    private Annotation fieldTA;
-    private Annotation innerTA;
-    private Annotation[] arrayTA = new Annotation[4];
-    private Annotation[] mapTA = new Annotation[5];
-
-    // Method type annotations
-    private Annotation returnTA, methodTypeParameterTA, formalParameterTA, throwsTA;
-
-    private void testTransformAndVerify()
-        throws NoSuchFieldException, NoSuchMethodException {
-
-        Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
-        Class<?> myClass = c;
-
-        /*
-         * Verify that the expected annotations are where they should be before transform.
-         */
-        verifyClassTypeAnnotations(c);
-        verifyFieldTypeAnnotations(c);
-        verifyMethodTypeAnnotations(c);
-
-        try {
-            inst.addTransformer(new Transformer(), true);
-            inst.retransformClasses(myClass);
-        } catch (UnmodifiableClassException e) {
-            throw new RuntimeException(e);
-        }
-
-        /*
-         * Verify that the expected annotations are where they should be after transform.
-         * Also verify that before and after are equal.
-         */
-        verifyClassTypeAnnotations(c);
-        verifyFieldTypeAnnotations(c);
-        verifyMethodTypeAnnotations(c);
-    }
-
-    private void verifyClassTypeAnnotations(Class c) {
-        Annotation anno;
-
-        anno = c.getTypeParameters()[0].getAnnotations()[0];
-        verifyTestAnn(classTypeParameterTA, anno, "classTypeParameter");
-        classTypeParameterTA = anno;
-
-        anno = c.getAnnotatedSuperclass().getAnnotations()[0];
-        verifyTestAnn(extendsTA, anno, "extends");
-        extendsTA = anno;
-
-        anno = c.getAnnotatedInterfaces()[0].getAnnotations()[0];
-        verifyTestAnn(implementsTA, anno, "implements");
-        implementsTA = anno;
-    }
-
-    private void verifyFieldTypeAnnotations(Class c)
-        throws NoSuchFieldException, NoSuchMethodException {
-
-        verifyBasicFieldTypeAnnotations(c);
-        verifyInnerFieldTypeAnnotations(c);
-        verifyArrayFieldTypeAnnotations(c);
-        verifyMapFieldTypeAnnotations(c);
-    }
-
-    private void verifyBasicFieldTypeAnnotations(Class c)
-        throws NoSuchFieldException, NoSuchMethodException {
-
-        Annotation anno = c.getDeclaredField("typeAnnotatedBoolean").getAnnotatedType().getAnnotations()[0];
-        verifyTestAnn(fieldTA, anno, "field");
-        fieldTA = anno;
-    }
-
-    private void verifyInnerFieldTypeAnnotations(Class c)
-        throws NoSuchFieldException, NoSuchMethodException {
-
-        AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType();
-        Annotation anno = at.getAnnotations()[0];
-        verifyTestAnn(innerTA, anno, "inner");
-        innerTA = anno;
-    }
-
-    private void verifyArrayFieldTypeAnnotations(Class c)
-        throws NoSuchFieldException, NoSuchMethodException {
-
-        Annotation anno;
-        AnnotatedType at;
-
-        at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType();
-        anno = at.getAnnotations()[0];
-        verifyTestAnn(arrayTA[0], anno, "array1");
-        arrayTA[0] = anno;
-
-        for (int i = 1; i <= 3; i++) {
-            at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
-            anno = at.getAnnotations()[0];
-            verifyTestAnn(arrayTA[i], anno, "array" + (i + 1));
-            arrayTA[i] = anno;
-        }
-    }
-
-    private void verifyMapFieldTypeAnnotations(Class c)
-        throws NoSuchFieldException, NoSuchMethodException {
-
-        Annotation anno;
-        AnnotatedType atBase;
-        AnnotatedType atParameter;
-        atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType();
-
-        anno = atBase.getAnnotations()[0];
-        verifyTestAnn(mapTA[0], anno, "map1");
-        mapTA[0] = anno;
-
-        atParameter =
-            ((AnnotatedParameterizedType) atBase).
-            getAnnotatedActualTypeArguments()[0];
-        anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0];
-        verifyTestAnn(mapTA[1], anno, "map2");
-        mapTA[1] = anno;
-
-        anno =
-            ((AnnotatedWildcardType) atParameter).
-            getAnnotatedUpperBounds()[0].getAnnotations()[0];
-        verifyTestAnn(mapTA[2], anno, "map3");
-        mapTA[2] = anno;
-
-        atParameter =
-            ((AnnotatedParameterizedType) atBase).
-            getAnnotatedActualTypeArguments()[1];
-        anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0];
-        verifyTestAnn(mapTA[3], anno, "map4");
-        mapTA[3] = anno;
-
-        anno =
-            ((AnnotatedParameterizedType) atParameter).
-            getAnnotatedActualTypeArguments()[0].getAnnotations()[0];
-        verifyTestAnn(mapTA[4], anno, "map5");
-        mapTA[4] = anno;
-    }
-
-    private void verifyMethodTypeAnnotations(Class c)
-        throws NoSuchFieldException, NoSuchMethodException {
-        Annotation anno;
-        Executable typeAnnotatedMethod =
-            c.getDeclaredMethod("typeAnnotatedMethod", TypeAnnotatedTestClass.class);
-
-        anno = typeAnnotatedMethod.getAnnotatedReturnType().getAnnotations()[0];
-        verifyTestAnn(returnTA, anno, "return");
-        returnTA = anno;
-
-        anno = typeAnnotatedMethod.getTypeParameters()[0].getAnnotations()[0];
-        verifyTestAnn(methodTypeParameterTA, anno, "methodTypeParameter");
-        methodTypeParameterTA = anno;
-
-        anno = typeAnnotatedMethod.getAnnotatedParameterTypes()[0].getAnnotations()[0];
-        verifyTestAnn(formalParameterTA, anno, "formalParameter");
-        formalParameterTA = anno;
-
-        anno = typeAnnotatedMethod.getAnnotatedExceptionTypes()[0].getAnnotations()[0];
-        verifyTestAnn(throwsTA, anno, "throws");
-        throwsTA = anno;
-    }
-
-    private static void verifyTestAnn(Annotation verifyAgainst, Annotation anno, String expectedSite) {
-        verifyTestAnnSite(anno, expectedSite);
-
-        // When called before transform verifyAgainst will be null, when called
-        // after transform it will be the annotation from before the transform
-        if (verifyAgainst != null) {
-            assertTrue(anno.equals(verifyAgainst),
-                       "Annotations do not match before and after." +
-                       " Before: \"" + verifyAgainst + "\", After: \"" + anno + "\"");
-        }
-    }
-
-    private static void verifyTestAnnSite(Annotation testAnn, String expectedSite) {
-        String expectedAnn = "@TestAnn(site=\"" + expectedSite + "\")";
-        assertTrue(testAnn.toString().equals(expectedAnn),
-                   "Expected \"" + expectedAnn + "\", got \"" + testAnn + "\"");
-    }
-
-    public static class TypeAnnotatedTestClass <@TestAnn(site="classTypeParameter") S,T>
-            extends @TestAnn(site="extends") Thread
-            implements @TestAnn(site="implements") Runnable {
-
-        public @TestAnn(site="field") boolean typeAnnotatedBoolean;
-
-        public
-            RedefineAnnotations.
-            @TestAnn(site="inner") TypeAnnotatedTestClass
-            typeAnnotatedInner;
-
-        public
-            @TestAnn(site="array4") boolean
-            @TestAnn(site="array1") []
-            @TestAnn(site="array2") []
-            @TestAnn(site="array3") []
-            typeAnnotatedArray;
-
-        public @TestAnn(site="map1") Map
-            <@TestAnn(site="map2") ? extends @TestAnn(site="map3") String,
-            @TestAnn(site="map4")  List<@TestAnn(site="map5")  Object>> typeAnnotatedMap;
-
-        public int dummy1;
-        public int dummy2;
-        public int dummy3;
-
-        @TestAnn(site="return") <@TestAnn(site="methodTypeParameter") U,V> Class
-            typeAnnotatedMethod(@TestAnn(site="formalParameter") TypeAnnotatedTestClass arg)
-            throws @TestAnn(site="throws") ClassNotFoundException {
-
-            @TestAnn(site="local_variable_type") int foo = 0;
-            throw new ClassNotFoundException();
-        }
-
-        public void run() {}
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineDeleteJmethod.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8181171
- * @summary Test deleting static method pointing to by a jmethod
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/native/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineDeleteJmethod
- */
-
-class B {
-    private static int deleteMe() { System.out.println("deleteMe called"); return 5; }
-    public static int callDeleteMe() { return deleteMe(); }
-}
-
-public class RedefineDeleteJmethod {
-
-    public static String newB =
-        "class B {" +
-            "public static int callDeleteMe() { return 6; }" +
-        "}";
-
-    public static String newerB =
-        "class B {" +
-            "private static int deleteMe() { System.out.println(\"deleteMe (2) called\"); return 7; }" +
-            "public static int callDeleteMe() { return deleteMe(); }" +
-        "}";
-
-
-    static {
-        System.loadLibrary("RedefineDeleteJmethod");
-    }
-
-    static native int jniCallDeleteMe();
-
-    static void test(int expected, boolean nsme_expected) throws Exception {
-        // Call through static method
-        int res = B.callDeleteMe();
-        System.out.println("Result = " + res);
-        if (res != expected) {
-            throw new Error("returned " + res + " expected " + expected);
-        }
-
-        // Call through jmethodID, saved from first call.
-        try {
-            res = jniCallDeleteMe();
-            if (nsme_expected) {
-                throw new RuntimeException("Failed, NoSuchMethodError expected");
-            }
-            if (res != expected) {
-                throw new Error("returned " + res + " expected " + expected);
-            }
-        } catch (NoSuchMethodError ex) {
-            if (!nsme_expected) {
-                throw new RuntimeException("Failed, NoSuchMethodError not expected");
-            }
-            System.out.println("Passed, NoSuchMethodError expected");
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
-        test(5, false);
-        RedefineClassHelper.redefineClass(B.class, newB);
-        test(6, true);
-        RedefineClassHelper.redefineClass(B.class, newerB);
-        test(7, true);
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineDoubleDelete.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8178870 8010319
- * @summary Redefine class with CFLH twice to test deleting the cached_class_file
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/native -Xlog:redefine+class+load+exceptions -agentlib:RedefineDoubleDelete -javaagent:redefineagent.jar RedefineDoubleDelete
- */
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-// The ClassFileLoadHook for this class turns foo into faa and prints out faa.
-class RedefineDoubleDelete_B {
-    int faa() { System.out.println("foo"); return 1; }
-}
-
-public class RedefineDoubleDelete {
-
-    // Class gets a redefinition error because it adds a data member
-    public static String newB =
-                "class RedefineDoubleDelete_B {" +
-                "   int count1 = 0;" +
-                "}";
-
-    public static String newerB =
-                "class RedefineDoubleDelete_B { " +
-                "   int faa() { System.out.println(\"baa\"); return 2; }" +
-                "}";
-
-    public static void main(String args[]) throws Exception {
-
-        RedefineDoubleDelete_B b = new RedefineDoubleDelete_B();
-        int val = b.faa();
-        if (val != 1) {
-            throw new RuntimeException("return value wrong " + val);
-        }
-
-        // Redefine B twice to get cached_class_file in both B scratch classes
-        try {
-            RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
-        } catch (java.lang.UnsupportedOperationException e) {
-            // this is expected
-        }
-        try {
-            RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
-        } catch (java.lang.UnsupportedOperationException e) {
-            // this is expected
-        }
-
-        // Do a full GC.
-        System.gc();
-
-        // Redefine with a compatible class
-        RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newerB);
-        val = b.faa();
-        if (val != 2) {
-            throw new RuntimeException("return value wrong " + val);
-        }
-
-        // Do another full GC to clean things up.
-        System.gc();
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineFinalizer.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * @test
- * @bug 6904403 8010319
- * @summary Don't assert if we redefine finalize method
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
- */
-
-/*
- * Regression test for hitting:
- *
- * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
- *
- * when redefining finalizer method
- */
-
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineFinalizer_B {
-    protected void finalize() {
-        // should be empty
-    }
-}
-
-public class RedefineFinalizer {
-
-    public static String newB =
-                "class RedefineFinalizer_B {" +
-                "   protected void finalize() { " +
-                "       System.out.println(\"Finalizer called\");" +
-                "   }" +
-                "}";
-
-    public static void main(String[] args) throws Exception {
-        RedefineClassHelper.redefineClass(RedefineFinalizer_B.class, newB);
-
-        A a = new A();
-    }
-
-    static class A extends RedefineFinalizer_B {
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceCall.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8174962 8010319
- * @summary Redefine class with interface method call
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=trace RedefineInterfaceCall
- */
-
-import static jdk.test.lib.Asserts.assertEquals;
-
-interface I1 { default int m() { return 0; } }
-interface I2 extends I1 {}
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineInterfaceCall_C implements I2 {
-    public int test(I2 i) {
-        return i.m(); // invokeinterface cpCacheEntry
-    }
-}
-
-public class RedefineInterfaceCall {
-
-    static String newI1 =
-      "interface I1 { default int m() { return 1; } }";
-
-    static String newC =
-        "class RedefineInterfaceCall_C implements I2 { " +
-        "  public int test(I2 i) { " +
-        "    return i.m(); " +
-        "  } " +
-        "} ";
-
-    static int test(I2 i) {
-        return i.m(); // invokeinterface cpCacheEntry
-    }
-
-    public static void main(String[] args) throws Exception {
-        RedefineInterfaceCall_C c = new RedefineInterfaceCall_C();
-
-        assertEquals(test(c),   0);
-        assertEquals(c.test(c), 0);
-
-        RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
-
-        assertEquals(c.test(c), 0);
-
-        RedefineClassHelper.redefineClass(I1.class, newI1);
-
-        assertEquals(test(c),   1);
-        assertEquals(c.test(c), 1);
-
-        RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
-
-        assertEquals(c.test(c), 1);
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceMethods.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * 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
- * 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 8081800 8010319
- * @summary Redefine private and default interface methods
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineInterfaceMethods
- */
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-interface RedefineInterfaceMethods_B {
-    int ORIGINAL_RETURN = 1;
-    int NEW_RETURN = 2;
-    private int privateMethod() {
-        return ORIGINAL_RETURN;
-    }
-    public default int defaultMethod() {
-        return privateMethod();
-    }
-}
-
-public class RedefineInterfaceMethods {
-
-    static final int RET = -2;
-
-    public static String redefinedPrivateMethod =
-        "interface RedefineInterfaceMethods_B {" +
-        "    int ORIGINAL_RETURN = 1;" +
-        "    int NEW_RETURN = 2;" +
-        "    private int privateMethod() {" +
-        "        return NEW_RETURN;" +
-        "    }" +
-        "    public default int defaultMethod() {" +
-        "       return privateMethod();" +
-        "    }" +
-        "}";
-
-    public static String redefinedDefaultMethod =
-        "interface RedefineInterfaceMethods_B {" +
-        "    int ORIGINAL_RETURN = 1;" +
-        "    int NEW_RETURN = 2;" +
-        "    private int privateMethod() {" +
-        "        return ORIGINAL_RETURN;" +
-        "    }" +
-        "    public default int defaultMethod() {" +
-        "       return RedefineInterfaceMethods.RET;" +
-        "    }" +
-        "}";
-
-    static class Impl implements RedefineInterfaceMethods_B {
-    }
-
-
-    public static void main(String[] args) throws Exception {
-
-        Impl impl = new Impl();
-
-        int res = impl.defaultMethod();
-        if (res != RedefineInterfaceMethods_B.ORIGINAL_RETURN)
-            throw new Error("defaultMethod returned " + res +
-                            " expected " + RedefineInterfaceMethods_B.ORIGINAL_RETURN);
-
-        RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedPrivateMethod);
-
-        res = impl.defaultMethod();
-        if (res != RedefineInterfaceMethods_B.NEW_RETURN)
-            throw new Error("defaultMethod returned " + res +
-                            " expected " + RedefineInterfaceMethods_B.NEW_RETURN);
-
-        System.gc();
-
-        RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedDefaultMethod);
-
-        res = impl.defaultMethod();
-        if (res != RET)
-            throw new Error("defaultMethod returned " + res +
-                            " expected " + RET);
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineLeak.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 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
- * @library /test/lib
- * @summary Test that redefinition reuses metaspace blocks that are freed
- * @modules java.base/jdk.internal.misc
- * @modules java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineLeak buildagent
- * @run main/othervm/timeout=6000  RedefineLeak runtest
- */
-
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.lang.RuntimeException;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.Instrumentation;
-import java.security.ProtectionDomain;
-import java.lang.instrument.IllegalClassFormatException;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class RedefineLeak {
-    static class Tester {}
-
-    static class LoggingTransformer implements ClassFileTransformer {
-        static int transformCount = 0;
-
-        public LoggingTransformer() {}
-
-        public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
-            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
-
-            transformCount++;
-            if (transformCount % 1000 == 0) System.out.println("transformCount:" + transformCount);
-            return null;
-        }
-    }
-
-    public static void premain(String agentArgs, Instrumentation inst) throws Exception {
-        LoggingTransformer t = new LoggingTransformer();
-        inst.addTransformer(t, true);
-        {
-            Class demoClass = Class.forName("RedefineLeak$Tester");
-
-            for (int i = 0; i < 10000; i++) {
-               inst.retransformClasses(demoClass);
-            }
-        }
-        System.gc();
-    }
-    private static void buildAgent() {
-        try {
-            ClassFileInstaller.main("RedefineLeak");
-        } catch (Exception e) {
-            throw new RuntimeException("Could not write agent classfile", e);
-        }
-
-        try {
-            PrintWriter pw = new PrintWriter("MANIFEST.MF");
-            pw.println("Premain-Class: RedefineLeak");
-            pw.println("Agent-Class: RedefineLeak");
-            pw.println("Can-Redefine-Classes: true");
-            pw.println("Can-Retransform-Classes: true");
-            pw.close();
-        } catch (FileNotFoundException e) {
-            throw new RuntimeException("Could not write manifest file for the agent", e);
-        }
-
-        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
-        if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineLeak.class" })) {
-            throw new RuntimeException("Could not write the agent jar file");
-        }
-    }
-    public static void main(String argv[]) throws Exception {
-        if (argv.length == 1 && argv[0].equals("buildagent")) {
-            buildAgent();
-            return;
-        }
-        if (argv.length == 1 && argv[0].equals("runtest")) {
-            // run outside of jtreg to not OOM on jtreg classes that are loaded after metaspace is full
-            String[] javaArgs1 = { "-XX:MetaspaceSize=12m", "-XX:MaxMetaspaceSize=12m",
-                                   "-javaagent:redefineagent.jar", "RedefineLeak"};
-            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
-
-            OutputAnalyzer output = new OutputAnalyzer(pb.start());
-            output.shouldContain("transformCount:10000");
-        }
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefinePreviousVersions.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * 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
- * 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 8165246 8010319
- * @summary Test has_previous_versions flag and processing during class unloading.
- * @requires vm.opt.final.ClassUnloading
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm RedefinePreviousVersions test
- */
-
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-// package access top-level classes to avoid problem with RedefineClassHelper
-// and nested types.
-
-class RedefinePreviousVersions_B { }
-
-class RedefinePreviousVersions_Running {
-    public static volatile boolean stop = false;
-    public static volatile boolean running = false;
-    static void localSleep() {
-        try {
-            Thread.sleep(10); // sleep for 10 ms
-        } catch(InterruptedException ie) {
-        }
-    }
-
-    public static void infinite() {
-        running = true;
-        while (!stop) { localSleep(); }
-    }
-}
-
-
-
-public class RedefinePreviousVersions {
-
-    public static String newB =
-                "class RedefinePreviousVersions_B {" +
-                "}";
-
-    public static String newRunning =
-        "class RedefinePreviousVersions_Running {" +
-        "    public static volatile boolean stop = true;" +
-        "    public static volatile boolean running = true;" +
-        "    static void localSleep() { }" +
-        "    public static void infinite() { }" +
-        "}";
-
-    public static void main(String[] args) throws Exception {
-
-        if (args.length > 0) {
-
-            // java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions
-            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar",
-               "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
-               "RedefinePreviousVersions");
-            new OutputAnalyzer(pb.start())
-              .shouldContain("Class unloading: has_previous_versions = false")
-              .shouldContain("Class unloading: has_previous_versions = true")
-              .shouldHaveExitValue(0);
-            return;
-        }
-
-        // Redefine a class and create some garbage
-        // Since there are no methods running, the previous version is never added to the
-        // previous_version_list and the flag _has_previous_versions should stay false
-        RedefineClassHelper.redefineClass(RedefinePreviousVersions_B.class, newB);
-
-        for (int i = 0; i < 10 ; i++) {
-            String s = new String("some garbage");
-            System.gc();
-        }
-
-        // Start a class that has a method running
-        new Thread() {
-            public void run() {
-                RedefinePreviousVersions_Running.infinite();
-            }
-        }.start();
-
-        while (!RedefinePreviousVersions_Running.running) {
-            Thread.sleep(10); // sleep for 10 ms
-        }
-
-        // Since a method of newRunning is running, this class should be added to the previous_version_list
-        // of Running, and _has_previous_versions should return true at class unloading.
-        RedefineClassHelper.redefineClass(RedefinePreviousVersions_Running.class, newRunning);
-
-        for (int i = 0; i < 10 ; i++) {
-            String s = new String("some garbage");
-            System.gc();
-        }
-
-        // purge should clean everything up, except Xcomp it might not.
-        RedefinePreviousVersions_Running.stop = true;
-
-        for (int i = 0; i < 10 ; i++) {
-            String s = new String("some garbage");
-            System.gc();
-        }
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethods.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * @test
- * @bug 8055008 8197901 8010319
- * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace,class+loader+data=debug,safepoint+cleanup,gc+phases=debug:rt.log RedefineRunningMethods
- */
-
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineRunningMethods_B {
-    static int count1 = 0;
-    static int count2 = 0;
-    public static volatile boolean stop = false;
-    static void localSleep() {
-        try{
-            Thread.currentThread().sleep(10);//sleep for 10 ms
-        } catch(InterruptedException ie) {
-        }
-    }
-
-    public static void infinite() {
-        while (!stop) { count1++; localSleep(); }
-    }
-    public static void infinite_emcp() {
-        while (!stop) { count2++; localSleep(); }
-    }
-}
-
-public class RedefineRunningMethods {
-
-    public static String newB =
-                "class RedefineRunningMethods_B {" +
-                "   static int count1 = 0;" +
-                "   static int count2 = 0;" +
-                "   public static volatile boolean stop = false;" +
-                "  static void localSleep() { " +
-                "    try{ " +
-                "      Thread.currentThread().sleep(10);" +
-                "    } catch(InterruptedException ie) { " +
-                "    } " +
-                " } " +
-                "   public static void infinite() { " +
-                "       System.out.println(\"infinite called\");" +
-                "   }" +
-                "   public static void infinite_emcp() { " +
-                "       while (!stop) { count2++; localSleep(); }" +
-                "   }" +
-                "}";
-
-    public static String evenNewerB =
-                "class RedefineRunningMethods_B {" +
-                "   static int count1 = 0;" +
-                "   static int count2 = 0;" +
-                "   public static volatile boolean stop = false;" +
-                "  static void localSleep() { " +
-                "    try{ " +
-                "      Thread.currentThread().sleep(1);" +
-                "    } catch(InterruptedException ie) { " +
-                "    } " +
-                " } " +
-                "   public static void infinite() { }" +
-                "   public static void infinite_emcp() { " +
-                "       System.out.println(\"infinite_emcp now obsolete called\");" +
-                "   }" +
-                "}";
-
-
-    public static void main(String[] args) throws Exception {
-
-        new Thread() {
-            public void run() {
-                RedefineRunningMethods_B.infinite();
-            }
-        }.start();
-
-        new Thread() {
-            public void run() {
-                RedefineRunningMethods_B.infinite_emcp();
-            }
-        }.start();
-
-        RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, newB);
-
-        System.gc();
-
-        RedefineRunningMethods_B.infinite();
-
-        // Start a thread with the second version of infinite_emcp running
-        new Thread() {
-            public void run() {
-                RedefineRunningMethods_B.infinite_emcp();
-            }
-        }.start();
-
-        for (int i = 0; i < 20 ; i++) {
-            String s = new String("some garbage");
-            System.gc();
-        }
-
-        RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, evenNewerB);
-        System.gc();
-
-        for (int i = 0; i < 20 ; i++) {
-            RedefineRunningMethods_B.infinite();
-            String s = new String("some garbage");
-            System.gc();
-        }
-
-        RedefineRunningMethods_B.infinite_emcp();
-
-        // purge should clean everything up.
-        RedefineRunningMethods_B.stop = true;
-
-        for (int i = 0; i < 20 ; i++) {
-            RedefineRunningMethods_B.infinite();
-            String s = new String("some garbage");
-            System.gc();
-        }
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +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 8087315 8010319
- * @summary Get old method's stack trace elements after GC
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
- */
-
-import static jdk.test.lib.Asserts.*;
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-class RedefineRunningMethodsWithBacktrace_B {
-    static int count1 = 0;
-    static int count2 = 0;
-    public static volatile boolean stop = false;
-    static void localSleep() {
-        try {
-            Thread.sleep(10);//sleep for 10 ms
-        } catch(InterruptedException ie) {
-        }
-    }
-
-    public static void infinite() {
-        while (!stop) { count1++; localSleep(); }
-    }
-    public static void throwable() {
-        // add some stuff to the original constant pool
-        String s1 = new String ("string1");
-        String s2 = new String ("string2");
-        String s3 = new String ("string3");
-        String s4 = new String ("string4");
-        String s5 = new String ("string5");
-        String s6 = new String ("string6");
-        String s7 = new String ("string7");
-        String s8 = new String ("string8");
-        String s9 = new String ("string9");
-        String s10 = new String ("string10");
-        String s11 = new String ("string11");
-        String s12 = new String ("string12");
-        String s13 = new String ("string13");
-        String s14 = new String ("string14");
-        String s15 = new String ("string15");
-        String s16 = new String ("string16");
-        String s17 = new String ("string17");
-        String s18 = new String ("string18");
-        String s19 = new String ("string19");
-        throw new RuntimeException("throwable called");
-    }
-}
-
-public class RedefineRunningMethodsWithBacktrace {
-
-    public static String newB =
-                "class RedefineRunningMethodsWithBacktrace_B {" +
-                "   static int count1 = 0;" +
-                "   static int count2 = 0;" +
-                "   public static volatile boolean stop = false;" +
-                "  static void localSleep() { " +
-                "    try{ " +
-                "      Thread.sleep(10);" +
-                "    } catch(InterruptedException ie) { " +
-                "    } " +
-                " } " +
-                "   public static void infinite() { " +
-                "       System.out.println(\"infinite called\");" +
-                "   }" +
-                "   public static void throwable() { " +
-                "       throw new RuntimeException(\"throwable called\");" +
-                "   }" +
-                "}";
-
-    public static String evenNewerB =
-                "class RedefineRunningMethodsWithBacktrace_B {" +
-                "   static int count1 = 0;" +
-                "   static int count2 = 0;" +
-                "   public static volatile boolean stop = false;" +
-                "  static void localSleep() { " +
-                "    try{ " +
-                "      Thread.sleep(1);" +
-                "    } catch(InterruptedException ie) { " +
-                "    } " +
-                " } " +
-                "   public static void infinite() { }" +
-                "   public static void throwable() { " +
-                "       throw new RuntimeException(\"throwable called\");" +
-                "   }" +
-                "}";
-
-    private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
-        System.out.println("touchRedefinedMethodInBacktrace: ");
-        throwable.printStackTrace();  // this actually crashes with the bug in
-                                      // java_lang_StackTraceElement::create()
-
-        // Make sure that we can convert the backtrace, which is referring to
-        // the redefined method, to a  StrackTraceElement[] without crashing.
-        StackTraceElement[] stackTrace = throwable.getStackTrace();
-        for (int i = 0; i < stackTrace.length; i++) {
-            StackTraceElement frame = stackTrace[i];
-            assertNotNull(frame.getClassName(),
-              "\nTest failed: trace[" + i + "].getClassName() returned null");
-            assertNotNull(frame.getMethodName(),
-              "\nTest failed: trace[" + i + "].getMethodName() returned null");
-        }
-    }
-
-    private static Throwable getThrowableInB() {
-        Throwable t = null;
-        try {
-            RedefineRunningMethodsWithBacktrace_B.throwable();
-        } catch (Exception e) {
-            t = e;
-            // Don't print here because Throwable will cache the constructed stacktrace
-            // e.printStackTrace();
-        }
-        return t;
-    }
-
-
-    public static void main(String[] args) throws Exception {
-
-        new Thread() {
-            public void run() {
-                RedefineRunningMethodsWithBacktrace_B.infinite();
-            }
-        }.start();
-
-        Throwable t1 = getThrowableInB();
-
-        RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, newB);
-
-        System.gc();
-
-        Throwable t2 = getThrowableInB();
-
-        RedefineRunningMethodsWithBacktrace_B.infinite();
-
-        for (int i = 0; i < 20 ; i++) {
-            String s = new String("some garbage");
-            System.gc();
-        }
-
-        RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, evenNewerB);
-        System.gc();
-
-        Throwable t3 = getThrowableInB();
-
-        for (int i = 0; i < 20 ; i++) {
-            RedefineRunningMethodsWithBacktrace_B.infinite();
-            String s = new String("some garbage");
-            System.gc();
-        }
-
-        touchRedefinedMethodInBacktrace(t1);
-        touchRedefinedMethodInBacktrace(t2);
-        touchRedefinedMethodInBacktrace(t3);
-
-        // purge should clean everything up.
-        RedefineRunningMethodsWithBacktrace_B.stop = true;
-
-        for (int i = 0; i < 20 ; i++) {
-            RedefineRunningMethodsWithBacktrace_B.infinite();
-            String s = new String("some garbage");
-            System.gc();
-        }
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2014, 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 8076110
- * @summary Redefine running methods that have cached resolution errors
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.base/jdk.internal.org.objectweb.asm
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineRunningMethodsWithResolutionErrors
- */
-
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
-
-import java.lang.reflect.InvocationTargetException;
-
-public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
-
-    @Override
-    protected Class<?> findClass(String name) throws ClassNotFoundException {
-        if (name.equals("C")) {
-            byte[] b = loadC(false);
-            return defineClass(name, b, 0, b.length);
-        } else {
-            return super.findClass(name);
-        }
-    }
-
-    private static byte[] loadC(boolean redefine) {
-        ClassWriter cw = new ClassWriter(0);
-
-        cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
-        {
-            MethodVisitor mv;
-
-            mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
-            mv.visitCode();
-
-            // First time we run we will:
-            // 1) Cache resolution errors
-            // 2) Redefine the class / method
-            // 3) Try to read the resolution errors that were cached
-            //
-            // The redefined method will never run, throw error to be sure
-            if (redefine) {
-                createThrowRuntimeExceptionCode(mv, "The redefined method was called");
-            } else {
-                createMethodBody(mv);
-            }
-            mv.visitMaxs(3, 0);
-            mv.visitEnd();
-        }
-        cw.visitEnd();
-        return cw.toByteArray();
-    }
-
-    private static void createMethodBody(MethodVisitor mv) {
-        Label classExists = new Label();
-
-        // Cache resolution errors
-        createLoadNonExistentClassCode(mv, classExists);
-
-        // Redefine our own class and method
-        mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
-
-        // Provoke the same error again to make sure the resolution error cache works
-        createLoadNonExistentClassCode(mv, classExists);
-
-        // Test passed
-        mv.visitInsn(RETURN);
-
-        mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
-        mv.visitLabel(classExists);
-
-        createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
-    }
-
-    private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
-        Label tryLoadBegin = new Label();
-        Label tryLoadEnd = new Label();
-        Label catchLoadBlock = new Label();
-        mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
-
-        // Try to load a class that does not exist to provoke resolution errors
-        mv.visitLabel(tryLoadBegin);
-        mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
-        mv.visitLabel(tryLoadEnd);
-
-        // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
-        mv.visitJumpInsn(GOTO, classExists);
-
-        mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
-        mv.visitLabel(catchLoadBlock);
-
-        // Ignore the expected NoClassDefFoundError
-        mv.visitInsn(POP);
-    }
-
-    private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
-        mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
-        mv.visitInsn(DUP);
-        mv.visitLdcInsn(msg);
-        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
-        mv.visitInsn(ATHROW);
-    }
-
-    private static Class<?> c;
-
-    public static void redefine() throws Exception {
-        RedefineClassHelper.redefineClass(c, loadC(true));
-    }
-
-    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
-        c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
-        c.getMethod("m").invoke(null);
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineSubtractLambdaExpression.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +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 8193524
- * @summary Redefine a class' public static method that contains a lambda expression
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineSubtractLambdaExpression
- */
-
-interface MathOperation {
-    public int operation(int a, int b);
-}
-
-class B {
-    public static int operate(int a, int b, MathOperation mathOperation) {
-        return mathOperation.operation(a, b);
-    }
-    static int test_math(String p) {
-        System.out.println(p + " from class B's test_math method");
-        MathOperation subtraction = (int a, int b) -> a - b;
-        MathOperation addition = (int a, int b) -> a + b;
-        return operate(10, 5, addition);
-    }
-}
-
-public class RedefineSubtractLambdaExpression {
-
-    public static String newB =
-        "class B {" +
-        "    public static int operate(int a, int b, MathOperation mathOperation) {" +
-        "        return mathOperation.operation(a, b);" +
-        "    }" +
-        "    static int test_math(String p) {" +
-        "        MathOperation subtraction = (int a, int b) -> a - b;" +
-        "        return operate(10, 5, subtraction);" +
-        "    }" +
-        "}";
-
-    public static void main(String[] args) throws Exception {
-        int res = B.test_math("Hello");
-        System.out.println("Result = " + res);
-        if (res != 15) {
-            throw new Error("test_math returned " + res + " expected " + 15);
-        }
-        RedefineClassHelper.redefineClass(B.class, newB);
-
-        res = B.test_math("Hello");
-        if (res != 5)
-            throw new Error("test_math returned " + res + " expected " + 5);
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/TestMultipleClasses.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8139551
- * @summary Scalability problem with redefinition - multiple code cache walks
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- *          java.instrument
- *          jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -XX:CompileThreshold=100 -Xlog:redefine+class+nmethod=debug TestMultipleClasses
- */
-
-import java.lang.instrument.*;
-import java.lang.reflect.*;
-import jdk.test.lib.compiler.InMemoryJavaCompiler;
-
-public class TestMultipleClasses extends ClassLoader {
-
-    public static String B(int count) {
-        return new String("public class B" + count + " {" +
-                "   public static void compiledMethod() { " +
-                "       try{" +
-                "          Thread.sleep(1); " +
-                "       } catch(InterruptedException ie) {" +
-                "       }" +
-                "   }" +
-                "}");
-    }
-
-    static String newB(int count) {
-        return new String("public class B" + count + " {" +
-                "   public static void compiledMethod() { " +
-                "       System.out.println(\"compiledMethod called " + count + "\");" +
-                "   }" +
-                "}");
-    }
-
-    static int index = 0;
-
-    @Override
-    protected Class<?> findClass(String name) throws ClassNotFoundException {
-        if (name.equals("B" + index)) {
-            byte[] b = InMemoryJavaCompiler.compile(name, B(index));
-            return defineClass(name, b, 0, b.length);
-        } else {
-            return super.findClass(name);
-        }
-    }
-
-    static void runCompiledMethodMethods(Class c, int count) throws Exception {
-        // Run for a while so they compile.
-        Object o = c.newInstance();
-        Method m = c.getMethod("compiledMethod");
-        for (int i = 0; i < count; i++) {
-            m.invoke(o);
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
-
-        final int numberOfClasses = 20;
-        Class[] classes = new Class[numberOfClasses];
-        byte[][] newClass = new byte[numberOfClasses][];
-        ClassDefinition[] defs = new ClassDefinition[numberOfClasses];
-
-        TestMultipleClasses loader = new TestMultipleClasses();
-
-        // Load and start all the classes.
-        for (index = 0; index < numberOfClasses; index++) {
-            String name = new String("B" + index);
-            Class c = loader.findClass(name);
-
-            runCompiledMethodMethods(c, 500);
-            // Make class definition for redefinition
-            classes[index] = c;
-            newClass[index] = InMemoryJavaCompiler.compile(c.getName(), newB(index));
-            defs[index] = new ClassDefinition(c, newClass[index]);
-        }
-
-        long startTime = System.currentTimeMillis();
-
-        // Redefine all classes.
-        RedefineClassHelper.instrumentation.redefineClasses(defs);
-
-        long endTime = System.currentTimeMillis();
-
-        System.out.println("Redefinition took " + (endTime - startTime) + " milliseconds");
-
-        System.gc();
-
-        // Run all new classes.
-        for (index = 0; index < numberOfClasses; index++) {
-            runCompiledMethodMethods(classes[index], 1);
-        }
-    }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/libRedefineDeleteJmethod.c	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <jni.h>
-
-jmethodID mid;
-jclass cls;
-static int count = 0;
-
-JNIEXPORT jint JNICALL
-Java_RedefineDeleteJmethod_jniCallDeleteMe(JNIEnv* env, jobject obj) {
-
-    if (count == 0) {
-      count++;
-      cls = (*env)->FindClass(env, "B");
-      if (NULL == cls) {
-          (*env)->FatalError(env, "could not find class");
-      }
-
-      mid = (*env)->GetStaticMethodID(env, cls, "deleteMe", "()I");
-      if (NULL == mid) {
-          (*env)->FatalError(env, "could not find method");
-      }
-    }
-
-    return (*env)->CallStaticIntMethod(env, cls, mid);
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/libRedefineDoubleDelete.c	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- * 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 <stdio.h>
-#include <string.h>
-#include "jvmti.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef JNI_ENV_ARG
-
-#ifdef __cplusplus
-#define JNI_ENV_ARG(x, y) y
-#define JNI_ENV_PTR(x) x
-#else
-#define JNI_ENV_ARG(x,y) x, y
-#define JNI_ENV_PTR(x) (*x)
-#endif
-
-#endif
-
-#define TranslateError(err) "JVMTI error"
-
-static jvmtiEnv *jvmti = NULL;
-
-static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
-
-JNIEXPORT
-jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
-    return Agent_Initialize(jvm, options, reserved);
-}
-
-JNIEXPORT
-jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
-    return Agent_Initialize(jvm, options, reserved);
-}
-
-JNIEXPORT
-jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
-    return JNI_VERSION_9;
-}
-
-
-static jint newClassDataLen = 0;
-static unsigned char* newClassData = NULL;
-
-static jint
-getBytecodes(jvmtiEnv *jvmti_env,
-             jint class_data_len, const unsigned char* class_data) {
-    int i;
-    jint res;
-
-    newClassDataLen = class_data_len;
-    res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
-    if (res != JNI_OK) {
-        printf("    Unable to allocate bytes\n");
-        return JNI_ERR;
-    }
-    for (i = 0; i < newClassDataLen; i++) {
-        newClassData[i] = class_data[i];
-        // Rewrite oo in class to aa
-        if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
-            newClassData[i] = newClassData[i-1] = 'a';
-        }
-    }
-    printf("  ... copied bytecode: %d bytes\n", (int)newClassDataLen);
-    return JNI_OK;
-}
-
-
-static void JNICALL
-Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
-                           jclass class_being_redefined,
-                           jobject loader, const char* name, jobject protection_domain,
-                           jint class_data_len, const unsigned char* class_data,
-                           jint *new_class_data_len, unsigned char** new_class_data) {
-    if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
-        if (newClassData == NULL) {
-            jint res = getBytecodes(jvmti_env, class_data_len, class_data);
-            if (res == JNI_ERR) {
-              printf(">>>    ClassFileLoadHook event: class name %s FAILED\n", name);
-              return;
-            }
-            // Only change for first CFLH event.
-            *new_class_data_len = newClassDataLen;
-            *new_class_data = newClassData;
-        }
-        printf(">>>    ClassFileLoadHook event: class name %s\n", name);
-    }
-}
-
-static
-jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
-    jint res, size;
-    jvmtiCapabilities caps;
-    jvmtiEventCallbacks callbacks;
-    jvmtiError err;
-
-    res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
-        JVMTI_VERSION_9);
-    if (res != JNI_OK || jvmti == NULL) {
-        printf("    Error: wrong result of a valid call to GetEnv!\n");
-        return JNI_ERR;
-    }
-
-    printf("Enabling following capabilities: can_generate_all_class_hook_events, "
-           "can_retransform_classes, can_redefine_classes");
-    memset(&caps, 0, sizeof(caps));
-    caps.can_generate_all_class_hook_events = 1;
-    caps.can_retransform_classes = 1;
-    caps.can_redefine_classes = 1;
-    printf("\n");
-
-    err = (*jvmti)->AddCapabilities(jvmti, &caps);
-    if (err != JVMTI_ERROR_NONE) {
-        printf("    Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
-        return JNI_ERR;
-    }
-
-    size = (jint)sizeof(callbacks);
-
-    memset(&callbacks, 0, sizeof(callbacks));
-    callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
-
-    err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
-    if (err != JVMTI_ERROR_NONE) {
-        printf("    Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
-        return JNI_ERR;
-    }
-
-    err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
-    if (err != JVMTI_ERROR_NONE) {
-        printf("    Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
-        return JNI_ERR;
-    }
-
-    return JNI_OK;
-}
-
-#ifdef __cplusplus
-}
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Thread/MonitorCacheMaybeExpand_DeadLock.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4087516
+ * @summary Incorrect locking leads to deadlock in monitorCacheMaybeExpand.
+ * @author Anand Palaniswamy
+ * @build MonitorCacheMaybeExpand_DeadLock
+ * @run main/othervm MonitorCacheMaybeExpand_DeadLock
+ */
+
+/**
+ * Background on the bug:
+ *
+ *     The thread local monitor cache had a locking bug (till
+ *     1.2beta1) where two threads trying to expand the monitor cache
+ *     at the same time would cause deadlock. The code paths that the
+ *     two threads must be executing for this to happen is described
+ *     in the bug report.
+ *
+ * Caveat and red-flag:
+ *
+ *     Since deadlocks are very timing dependent, there is a good
+ *     chance this test case will not catch the bug most of the time
+ *     -- on your machine and setting, it is _possible_ that the two
+ *     threads might not try a monitorCacheExpand at the same
+ *     time. But in practice, on Solaris native threads, this program
+ *     deadlocks the VM in about 2 seconds pretty consistently,
+ *     whether MP or not.
+ *
+ *     The rationale for running this test despite this rather large
+ *     caveat is that at worst, it can do no harm.
+ *
+ * The idea:
+ *
+ *     Is to create two monitor hungry threads.
+ *
+ *     Originally Tom Rodriguez and I suspected that this weird state
+ *     of two threads trying to expand monitor cache can happen only
+ *     if:
+ *
+ *         Thread 1: Is in the middle of a monitorCacheMaybeExpand.
+ *         Thread 2: Runs GC and tries to freeClasses(). This causes
+ *                   sysFree() to be invoked, which in turn needs a
+ *                   mutex_lock -- and oops, we end up deadlocking
+ *                   with 1 on green_threads.
+ *
+ *     Which is why this test tries to cause class GC at regular
+ *     intervals.
+ *
+ *     Turns out that the GC is not required. Two instances of the
+ *     monitor hungry threads deadlock the VM pretty quick. :-) Infact
+ *     the static initializer in the forName'd classes running
+ *     alongside one of the hungry threads is sufficient to
+ *     deadlock. Still keep the GC stuff just-in-case (and also
+ *     because I wrote it :-).
+ *
+ */
+public class MonitorCacheMaybeExpand_DeadLock {
+
+    /**
+     * A monitor-hungry thread.
+     */
+    static class LotsaMonitors extends Thread {
+
+        /** How many recursions? Could cause Java stack overflow. */
+        static final int MAX_DEPTH = 800;
+
+        /** What is our depth? */
+        int depth = 0;
+
+        /** Thread ID */
+        int tid;
+
+        /** So output will have thread number. */
+        public LotsaMonitors(int tid, int depth) {
+            super("LotsaMonitors #" + new Integer(tid).toString());
+            this.tid = tid;
+            this.depth = depth;
+        }
+
+        /** Start a recursion that grabs monitors. */
+        public void run() {
+            System.out.println(">>>Starting " + this.toString() + " ...");
+            Thread.currentThread().yield();
+            this.recurse();
+            System.out.println("<<<Finished " + this.toString());
+        }
+
+        /** Every call to this method grabs an extra monitor. */
+        synchronized void recurse() {
+            if (this.depth > 0) {
+                new LotsaMonitors(tid, depth-1).recurse();
+            }
+        }
+    }
+
+    /**
+     * The test.
+     */
+    public static void main(String[] args) {
+        /* Start the two of these crazy threads. */
+        new LotsaMonitors(1, LotsaMonitors.MAX_DEPTH).start();
+        new LotsaMonitors(2, LotsaMonitors.MAX_DEPTH).start();
+
+        /* And sit there and GC for good measure. */
+        for (int i = 0; i < MAX_GC_ITERATIONS; i++) {
+            new LotsaMonitors(i+3, LotsaMonitors.MAX_DEPTH).start();
+            System.out.println(">>>Loading 10 classes and gc'ing ...");
+            Class[] classes = new Class[10];
+            fillClasses(classes);
+            classes = null;
+            System.gc();
+            Thread.currentThread().yield();
+            System.out.println("<<<Finished loading 10 classes and gc'ing");
+        }
+    }
+
+    /** How many times to GC? */
+    static final int MAX_GC_ITERATIONS = 10;
+
+    /** Load some classes into the array. */
+    static void fillClasses(Class[] classes) {
+        for (int i = 0; i < classes.length; i++) {
+            try {
+                classes[i] = Class.forName(classnames[i]);
+            } catch (ClassNotFoundException cnfe) {
+                cnfe.printStackTrace();
+            }
+        }
+    }
+
+    /** Some random classes to load. */
+    private static String[] classnames = {
+        "java.text.DecimalFormat",
+        "java.text.MessageFormat",
+        "java.util.GregorianCalendar",
+        "java.util.ResourceBundle",
+        "java.text.Collator",
+        "java.util.Date",
+        "java.io.Reader",
+        "java.io.Writer",
+        "java.lang.IllegalAccessException",
+        "java.lang.InstantiationException",
+        "java.lang.ClassNotFoundException",
+        "java.lang.CloneNotSupportedException",
+        "java.lang.InterruptedException",
+        "java.lang.NoSuchFieldException",
+        "java.lang.NoSuchMethodException",
+        "java.lang.RuntimeException",
+        "java.lang.ArithmeticException",
+        "java.lang.ArrayStoreException",
+        "java.lang.ClassCastException",
+        "java.lang.StringIndexOutOfBoundsException",
+        "java.lang.NegativeArraySizeException",
+        "java.lang.IllegalStateException",
+        "java.lang.IllegalArgumentException",
+        "java.lang.NumberFormatException",
+        "java.lang.IllegalThreadStateException",
+        "java.lang.IllegalMonitorStateException",
+        "java.lang.SecurityException",
+        "java.lang.ExceptionInInitializerError"
+    };
+
+}
--- a/test/hotspot/jtreg/runtime/Thread/SuspendAtExit.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/Thread/SuspendAtExit.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,6 +26,7 @@
  * @bug 8167108
  * @summary Stress test java.lang.Thread.suspend() at thread exit.
  * @run main/othervm -Xlog:thread+smr=debug SuspendAtExit
+ * @run main/othervm -Xlog:thread+smr=debug -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedSafepointInterval=1 -XX:+HandshakeALot SuspendAtExit
  */
 
 import java.util.concurrent.CountDownLatch;
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,10 @@
 
 /*
  * @test
- * @summary Run /runtime/RedefineTests/RedefineRunningMethods in AppCDS mode to
+ * @summary Run /serviceability/jvmti/RedefineClasses/RedefineRunningMethods in AppCDS mode to
  *          make sure class redefinition works with CDS.
  * @requires vm.cds
- * @library /test/lib /test/hotspot/jtreg/runtime/RedefineTests /test/hotspot/jtreg/runtime/appcds
+ * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/appcds
  * @modules java.compiler
  *          java.instrument
  *          jdk.jartool/sun.tools.jar
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,10 @@
 
 /*
  * @test
- * @summary Run /runtime/RedefineTests/RedefineRunningMethods in AppCDS mode to
+ * @summary Run /serviceability/jvmti/RedefineClasses/RedefineRunningMethods in AppCDS mode to
  *          make sure class redefinition works with CDS.
  * @requires vm.cds
- * @library /test/lib /test/hotspot/jtreg/runtime/RedefineTests /test/hotspot/jtreg/runtime/appcds
+ * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/appcds
  * @modules java.base/jdk.internal.misc
  * @modules java.compiler
  *          java.instrument
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/handshake/HandshakeSuspendExitTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test HandshakeSuspendExitTest
+ * @summary This test tries to stress the handshakes with new and exiting threads while suspending them.
+ * @library /testlibrary /test/lib
+ * @build HandshakeSuspendExitTest
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedSafepointInterval=1 -XX:+HandshakeALot HandshakeSuspendExitTest
+ */
+
+public class HandshakeSuspendExitTest  implements Runnable {
+
+    static Thread[] _suspend_threads = new Thread[16];
+    static volatile boolean _exit_now = false;
+    static java.util.concurrent.Semaphore _sem = new java.util.concurrent.Semaphore(0);
+
+    @Override
+    public void run() {
+        _sem.release();
+        while (!_exit_now) {
+            // Leave last 2 threads running.
+            for (int i = 0; i < _suspend_threads.length - 2; i++) {
+                if (Thread.currentThread() != thr) {
+                    thr.suspend();
+                    thr.resume();
+                }
+            }
+        }
+        _sem.release();
+    }
+
+    public static void main(String... args) throws Exception {
+        HandshakeSuspendExitTest test = new HandshakeSuspendExitTest();
+        // Fire-up suspend threads.
+        for (int i = 0; i < _suspend_threads.length; i++) {
+            _suspend_threads[i] = new Thread(test);
+        }
+        for (int i = 0; i < _suspend_threads.length; i++) {
+            _suspend_threads[i].start();
+        }
+        // Wait for all suspend-threads to start looping.
+        for (Thread thr : _suspend_threads) {
+            _sem.acquire();
+        }
+
+        // Fire-up exiting threads.
+        Thread[] exit_threads = new Thread[128];
+        for (int i = 0; i < exit_threads.length; i++) {
+            exit_threads[i] = new Thread();
+            exit_threads[i].start();
+        }
+
+        // Try to suspend them.
+        for (Thread thr : exit_threads) {
+            thr.suspend();
+        }
+        for (Thread thr : exit_threads) {
+            thr.resume();
+        }
+
+        // Start exit and join.
+        _exit_now = true;
+        int waiting = _suspend_threads.length;
+        do {
+            // Resume any worker threads that might have suspended
+            // each other at exactly the same time so they can see
+            // _exit_now and check in via the semaphore.
+            for (Thread thr : _suspend_threads) {
+                thr.resume();
+            }
+            while (_sem.tryAcquire()) {
+                --waiting;
+            }
+        } while (waiting > 0);
+        for (Thread thr : _suspend_threads) {
+            thr.join();
+        }
+        for (Thread thr : exit_threads) {
+            thr.join();
+        }
+    }
+}
--- a/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/handshake/HandshakeTransitionTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -62,6 +62,7 @@
                     true,
                     "-Djava.library.path=" + lib,
                     "-XX:+SafepointALot",
+                    "-XX:+HandshakeALot",
                     "-XX:GuaranteedSafepointInterval=20",
                     "-Xlog:ergo*",
                     "-XX:ParallelGCThreads=1",
--- a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkSuspendExitTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +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 HandshakeWalkSuspendExitTest
- * @summary This test tries to stress the handshakes with new and exiting threads while suspending them.
- * @library /testlibrary /test/lib
- * @build HandshakeWalkSuspendExitTest
- * @run driver ClassFileInstaller sun.hotspot.WhiteBox
- *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI HandshakeWalkSuspendExitTest
- */
-
-import jdk.test.lib.Asserts;
-import sun.hotspot.WhiteBox;
-
-public class HandshakeWalkSuspendExitTest  implements Runnable {
-
-    static final int _test_threads = 8;
-    static final int _test_exit_threads = 128;
-    static Thread[] _threads = new Thread[_test_threads];
-    static volatile boolean exit_now = false;
-    static java.util.concurrent.Semaphore _sem = new java.util.concurrent.Semaphore(0);
-
-    @Override
-    public void run() {
-        WhiteBox wb = WhiteBox.getWhiteBox();
-        while (!exit_now) {
-            _sem.release();
-            // We only suspend threads on even index and not ourself.
-            // Otherwise we can accidentially suspend all threads.
-            for (int i = 0; i < _threads.length; i += 2) {
-                wb.handshakeWalkStack(null /* ignored */, true /* stackwalk all threads */);
-                if (Thread.currentThread() != _threads[i]) {
-                    _threads[i].suspend();
-                    _threads[i].resume();
-                }
-            }
-            for (int i = 0; i < _threads.length; i += 2) {
-                wb.handshakeWalkStack(_threads[i] /* thread to stackwalk */, false /* stackwalk one thread */);
-                if (Thread.currentThread() != _threads[i]) {
-                    _threads[i].suspend();
-                    _threads[i].resume();
-                }
-            }
-        }
-    }
-
-    public static void main(String... args) throws Exception {
-        HandshakeWalkSuspendExitTest test = new HandshakeWalkSuspendExitTest();
-
-        for (int i = 0; i < _threads.length; i++) {
-            _threads[i] = new Thread(test);
-            _threads[i].start();
-        }
-        for (int i = 0; i < _test_threads; i++) {
-            _sem.acquire();
-        }
-        Thread[] exit_threads = new Thread[_test_exit_threads];
-        for (int i = 0; i < _test_exit_threads; i++) {
-            exit_threads[i] = new Thread(new Runnable() { public void run() {} });
-            exit_threads[i].start();
-        }
-        exit_now = true;
-        for (int i = 0; i < _threads.length; i++) {
-            _threads[i].join();
-        }
-        for (int i = 0; i < exit_threads.length; i++) {
-            exit_threads[i].join();
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/interpreter/WideStrictInline.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4169183
+ * @summary Check for correct inlining by the interpreter (widefp and strictfp).
+ *          The default is widefp.  A strictfp method was getting inlined
+ *          into a widefp method.
+ */
+
+import java.io.PrintStream;
+
+public class WideStrictInline {
+    static PrintStream out;
+    static float halfUlp;
+
+    static {
+        halfUlp = 1;
+        for ( int i = 127 - 24; i > 0; i-- )
+            halfUlp *= 2;
+    }
+
+    public static void main(String argv[]) throws Exception {
+        out = System.err;
+        pr(-1,"halfUlp",halfUlp);
+        WideStrictInline obj = new WideStrictInline();
+        for( int i=0; i<48; i++ )
+            obj.instanceMethod( i );
+    }
+
+    private static void pr(int i, String desc, float r) {
+        out.print(" i=("+i+") "+desc+" ; == "+r);
+        out.println(" , 0x"+Integer.toHexString(Float.floatToIntBits(r)));
+    }
+
+    private static strictfp float WideStrictInline(float par) {
+        return par;
+    }
+
+    public static strictfp float strictValue(int i) {
+        float r;
+        switch (i%4) {
+        case 0: r = -Float.MAX_VALUE;  break;
+        case 1: r =  Float.MAX_VALUE;  break;
+        case 2: r =  Float.MIN_VALUE;  break;
+        default : r = 1L << 24;
+        }
+        return r;
+    }
+
+    void instanceMethod (int i) throws Exception {
+        float r;
+        switch (i%4) {
+        case 0:
+            if (!Float.isInfinite( WideStrictInline(strictValue(i)*2) +
+                                   Float.MAX_VALUE ))
+                {
+                    pr(i,
+                       "WideStrictInline(-Float.MAX_VALUE * 2) " +
+                       "!= Float.NEGATIVE_INFINITY"
+                       ,WideStrictInline(strictValue(i)*2) + Float.MAX_VALUE);
+                }
+            r = WideStrictInline(strictValue(i)*2) + Float.MAX_VALUE;
+            if ( !Float.isInfinite( r ) ) {
+                pr(i,"r != Float.NEGATIVE_INFINITY",r);
+                throw new RuntimeException();
+            }
+            break;
+        case 1:
+            if (!Float.isInfinite(WideStrictInline(strictValue(i)+halfUlp) -
+                                  Float.MAX_VALUE )) {
+                pr(i,"WideStrictInline(Float.MAX_VALUE+halfUlp) " +
+                   "!= Float.POSITIVE_INFINITY"
+                   ,WideStrictInline(strictValue(i)+halfUlp) - Float.MAX_VALUE);
+            }
+            r = WideStrictInline(strictValue(i)+halfUlp) - Float.MAX_VALUE;
+            if ( !Float.isInfinite( r ) ) {
+                pr(i,"r != Float.POSITIVE_INFINITY",r);
+                throw new RuntimeException();
+            }
+            break;
+        case 2:
+            if (WideStrictInline(strictValue(i)/2) != 0) {
+                pr(i,"WideStrictInline(Float.MIN_VALUE/2) != 0",
+                   WideStrictInline(strictValue(i)/2));
+            }
+            r = WideStrictInline(strictValue(i)/2);
+            if ( r != 0 ) {
+                pr(i,"r != 0",r);
+                throw new RuntimeException();
+            }
+            break;
+        default:
+            if (WideStrictInline(strictValue(i)-0.5f) - strictValue(i) != 0) {
+                pr(i,"WideStrictInline(2^24-0.5) != 2^24",
+                   WideStrictInline(strictValue(i)-0.5f));
+            }
+            r = WideStrictInline(strictValue(i)-0.5f);
+            if ( r - strictValue(i) != 0 ) {
+                pr(i,"r != 2^24",r);
+                throw new RuntimeException();
+            }
+        }
+    }
+
+}
--- a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 8197901 8209758
  * @summary Redefine classes with enabling logging to verify Klass:external_name() during GC.
- * @comment This test is simplified version of runtime/RedefineTests/RedefineRunningMethods.java.
+ * @comment This test is simplified version of serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java.
  * @library /test/lib
  * @modules java.compiler
  *          java.instrument
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/ModulesSymLink.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019, Google Inc. 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.
+ */
+
+/*
+ * @test
+ * @summary Test with symbolic linked lib/modules
+ * @bug 8220095
+ * @requires (os.family == "solaris" | os.family == "linux" | os.family == "mac")
+ * @library /test/lib
+ * @modules java.management
+ *          jdk.jlink
+ * @run driver ModulesSymLink
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class ModulesSymLink {
+    static String java_home;
+    static String test_jdk;
+
+    public static void main(String[] args) throws Throwable {
+        java_home = System.getProperty("java.home");
+        test_jdk = System.getProperty("user.dir") + File.separator +
+                   "modulessymlink_jdk" + Long.toString(System.currentTimeMillis());
+
+        constructTestJDK();
+
+        ProcessBuilder pb = new ProcessBuilder(
+            test_jdk + File.separator + "bin" + File.separator + "java",
+            "-version");
+        OutputAnalyzer out = new OutputAnalyzer(pb.start());
+        out.shouldHaveExitValue(0);
+    }
+
+    // 1) Create a test JDK binary (jlink is used to help simplify the process,
+    //    alternatively a test JDK could be copied from JAVA_HOME.)
+    // 2) Rename the test JDK's lib/modules to lib/0.
+    // 3) Then create a link to lib/0 as lib/modules.
+    static void constructTestJDK() throws Throwable {
+        Path jlink = Paths.get(java_home, "bin", "jlink");
+        System.out.println("Jlink = " + jlink);
+        OutputAnalyzer out = ProcessTools.executeProcess(jlink.toString(),
+                  "--output", test_jdk,
+                  "--add-modules", "java.base");
+        out.shouldHaveExitValue(0);
+
+        Path modules = Paths.get(test_jdk, "lib", "modules");
+        Path renamed_modules = Paths.get(test_jdk, "lib", "0");
+        Files.move(modules, renamed_modules);
+        Files.createSymbolicLink(modules, renamed_modules);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/reflect/ReflectStackOverflow.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4185411
+ * @summary This program crashes in 1.1, but runs okay in 1.2.
+ * @run main/othervm -Xss512k ReflectStackOverflow
+ */
+import java.lang.reflect.*;
+
+public class ReflectStackOverflow {
+    private static final int COUNT = 11000;
+
+    public static void main(String[] cmdline) throws Throwable {
+        for (int i = 0; i < COUNT+1; i++) {
+            stuff(i);
+        }
+    }
+
+    private static void stuff(int count) throws Throwable {
+        if (count < COUNT)
+            return;  // don't do anything the first COUNT times.
+
+        try {
+            final Method method =
+                Method.class.getMethod
+                ("invoke", new Class[] { Object.class, Object[].class });
+
+            final Object[] args = new Object[] { method, null };
+            args[1] = args;
+
+            method.invoke(method, args); // "recursive reflection"
+            // exception should have been thrown by now...
+            System.out.println("how did I get here?");
+        } catch(Throwable t) {
+            int layers;
+            for(layers = 0; t instanceof InvocationTargetException; layers++)
+                t = ((InvocationTargetException)t).getTargetException();
+
+            System.err.println("Found " + layers + " layers of wrappers.");
+            if (!(t instanceof StackOverflowError)) {
+                throw t;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/verifier/BadSignatures.jcod	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * In this case, the signature for the fieldRef for str is missing its closing ';'.
+ *  public class BadFieldRef {
+ *      static String str = new String("Hi");
+ *      public static void m(String argv[]) {
+ *          System.out.println(str);
+ *      }
+ *  }
+*/
+class BadFieldRef {
+  0xCAFEBABE;
+  0; // minor version
+  57; // version
+  [38] { // Constant Pool
+    ; // first element is empty
+    Method #9 #21; // #1     at 0x0A
+    Field #22 #23; // #2     at 0x0F
+    Field #8 #24; // #3     at 0x14
+    Method #25 #26; // #4     at 0x19
+    class #27; // #5     at 0x1E
+    String #28; // #6     at 0x21
+    Method #5 #29; // #7     at 0x24
+    class #30; // #8     at 0x29
+    class #31; // #9     at 0x2C
+    Utf8 "str"; // #10     at 0x2F
+    Utf8 "Ljava/lang/String"; // #11     at 0x35  // Missing closing ';' !!
+    Utf8 "<init>"; // #12     at 0x4A
+    Utf8 "()V"; // #13     at 0x53
+    Utf8 "Code"; // #14     at 0x59
+    Utf8 "LineNumberTable"; // #15     at 0x60
+    Utf8 "m"; // #16     at 0x72
+    Utf8 "([Ljava/lang/String;)V"; // #17     at 0x76
+    Utf8 "<clinit>"; // #18     at 0x8F
+    Utf8 "SourceFile"; // #19     at 0x9A
+    Utf8 "BadFieldRef.java"; // #20     at 0xA7
+    NameAndType #12 #13; // #21     at 0xBA
+    class #32; // #22     at 0xBF
+    NameAndType #33 #34; // #23     at 0xC2
+    NameAndType #10 #11; // #24     at 0xC7
+    class #35; // #25     at 0xCC
+    NameAndType #36 #37; // #26     at 0xCF
+    Utf8 "java/lang/String"; // #27     at 0xD4
+    Utf8 "Hi"; // #28     at 0xE7
+    NameAndType #12 #37; // #29     at 0xEC
+    Utf8 "BadFieldRef"; // #30     at 0xF1
+    Utf8 "java/lang/Object"; // #31     at 0xFF
+    Utf8 "java/lang/System"; // #32     at 0x0112
+    Utf8 "out"; // #33     at 0x0125
+    Utf8 "Ljava/io/PrintStream;"; // #34     at 0x012B
+    Utf8 "java/io/PrintStream"; // #35     at 0x0143
+    Utf8 "println"; // #36     at 0x0159
+    Utf8 "(Ljava/lang/String;)V"; // #37     at 0x0163
+  } // Constant Pool
+
+  0x0021; // access [ ACC_PUBLIC ACC_SUPER ]
+  #8;// this_cpx
+  #9;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [1] { // fields
+    { // Member at 0x0185
+      0x0008; // access
+      #10; // name_cpx
+      #11; // sig_cpx
+      [0] { // Attributes
+      } // Attributes
+    } // Member
+  } // fields
+
+  [3] { // methods
+    { // Member at 0x018F
+      0x0001; // access
+      #12; // name_cpx
+      #13; // sig_cpx
+      [1] { // Attributes
+        Attr(#14, 29) { // Code at 0x0197
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#15, 6) { // LineNumberTable at 0x01AE
+              [1] { // LineNumberTable
+                0  1; //  at 0x01BA
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x01BA
+      0x0009; // access
+      #16; // name_cpx
+      #17; // sig_cpx
+      [1] { // Attributes
+        Attr(#14, 38) { // Code at 0x01C2
+          2; // max_stack
+          1; // max_locals
+          Bytes[10]{
+            0xB20002B20003B600;
+            0x04B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#15, 10) { // LineNumberTable at 0x01DE
+              [2] { // LineNumberTable
+                0  6; //  at 0x01EA
+                9  7; //  at 0x01EE
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x01EE
+      0x0008; // access
+      #18; // name_cpx
+      #13; // sig_cpx
+      [1] { // Attributes
+        Attr(#14, 37) { // Code at 0x01F6
+          3; // max_stack
+          0; // max_locals
+          Bytes[13]{
+            0xBB0005591206B700;
+            0x07B30003B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#15, 6) { // LineNumberTable at 0x0215
+              [1] { // LineNumberTable
+                0  3; //  at 0x0221
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#19, 2) { // SourceFile at 0x0223
+      #20;
+    } // end SourceFile
+  } // Attributes
+} // end class BadFieldRef
+
+
+
+/*
+ * In this case, the signature for the methodRef has an illegal embedded ';'.
+ *  public class BadMethodRef {
+ *      public static void main(java.la;ng.String argv[]) throws Throwable {
+ *          System.out.println(" World");
+ *      }
+ *  }
+*/
+class BadMethodRef {
+  0xCAFEBABE;
+  0; // minor version
+  57; // version
+  [32] { // Constant Pool
+    ; // first element is empty
+    Method #6 #17; // #1     at 0x0A
+    Field #18 #19; // #2     at 0x0F
+    String #20; // #3     at 0x14
+    Method #21 #22; // #4     at 0x17
+    class #23; // #5     at 0x1C
+    class #24; // #6     at 0x1F
+    Utf8 "<init>"; // #7     at 0x22
+    Utf8 "()V"; // #8     at 0x2B
+    Utf8 "Code"; // #9     at 0x31
+    Utf8 "LineNumberTable"; // #10     at 0x38
+    Utf8 "main"; // #11     at 0x4A
+    Utf8 "([Ljava/lang/String;)V"; // #12     at 0x51
+    Utf8 "Exceptions"; // #13     at 0x6A
+    class #25; // #14     at 0x77
+    Utf8 "SourceFile"; // #15     at 0x7A
+    Utf8 "BadMethodRef.java"; // #16     at 0x87
+    NameAndType #7 #8; // #17     at 0x9B
+    class #26; // #18     at 0xA0
+    NameAndType #27 #28; // #19     at 0xA3
+    Utf8 " World"; // #20     at 0xA8
+    class #29; // #21     at 0xB1
+    NameAndType #30 #31; // #22     at 0xB4
+    Utf8 "BadMethodRef"; // #23     at 0xB9
+    Utf8 "java/lang/Object"; // #24     at 0xC8
+    Utf8 "java/lang/Throwable"; // #25     at 0xDB
+    Utf8 "java/lang/System"; // #26     at 0xF1
+    Utf8 "out"; // #27     at 0x0104
+    Utf8 "Ljava/io/PrintStream;"; // #28     at 0x010A
+    Utf8 "java/io/PrintStream"; // #29     at 0x0122
+    Utf8 "println"; // #30     at 0x0138
+    Utf8 "(Ljava/la;ng/String;)V"; // #31     at 0x0142 // Illegal "la;ng"
+  } // Constant Pool
+
+  0x0021; // access [ ACC_PUBLIC ACC_SUPER ]
+  #5;// this_cpx
+  #6;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [2] { // methods
+    { // Member at 0x0166
+      0x0001; // access
+      #7; // name_cpx
+      #8; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0x016E
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0x0185
+              [1] { // LineNumberTable
+                0  1; //  at 0x0191
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0191
+      0x0009; // access
+      #11; // name_cpx
+      #12; // sig_cpx
+      [2] { // Attributes
+        Attr(#9, 37) { // Code at 0x0199
+          2; // max_stack
+          1; // max_locals
+          Bytes[9]{
+            0xB200021203B60004;
+            0xB1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 10) { // LineNumberTable at 0x01B4
+              [2] { // LineNumberTable
+                0  4; //  at 0x01C0
+                8  5; //  at 0x01C4
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+        ;
+        Attr(#13, 4) { // Exceptions at 0x01C4
+          [1] { // Exceptions
+            #14; //  at 0x01CE
+          }
+        } // end Exceptions
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#15, 2) { // SourceFile at 0x01D0
+      #16;
+    } // end SourceFile
+  } // Attributes
+} // end class BadMethodRef
+
+
+/*
+ * In this case, the signature for myMethod has an illegal embedded '['.
+ *  public class BadMethodSig {
+ *      public static void myMethod(Str[ing argv[]) throws Throwable {
+ *          System.out.println(" World");
+ *      }
+ *  }
+*/
+class BadMethodSig {
+  0xCAFEBABE;
+  0; // minor version
+  57; // version
+  [32] { // Constant Pool
+    ; // first element is empty
+    Method #6 #17; // #1     at 0x0A
+    Field #18 #19; // #2     at 0x0F
+    String #20; // #3     at 0x14
+    Method #21 #22; // #4     at 0x17
+    class #23; // #5     at 0x1C
+    class #24; // #6     at 0x1F
+    Utf8 "<init>"; // #7     at 0x22
+    Utf8 "()V"; // #8     at 0x2B
+    Utf8 "Code"; // #9     at 0x31
+    Utf8 "LineNumberTable"; // #10     at 0x38
+    Utf8 "myMethod"; // #11     at 0x4A
+    Utf8 "([Ljava/lang/Str[ing;)V"; // #12     at 0x55  // Illegal "Str[ing"
+    Utf8 "Exceptions"; // #13     at 0x6E
+    class #25; // #14     at 0x7B
+    Utf8 "SourceFile"; // #15     at 0x7E
+    Utf8 "BadMethodSig.java"; // #16     at 0x8B
+    NameAndType #7 #8; // #17     at 0x9F
+    class #26; // #18     at 0xA4
+    NameAndType #27 #28; // #19     at 0xA7
+    Utf8 " World"; // #20     at 0xAC
+    class #29; // #21     at 0xB5
+    NameAndType #30 #31; // #22     at 0xB8
+    Utf8 "BadMethodSig"; // #23     at 0xBD
+    Utf8 "java/lang/Object"; // #24     at 0xCC
+    Utf8 "java/lang/Throwable"; // #25     at 0xDF
+    Utf8 "java/lang/System"; // #26     at 0xF5
+    Utf8 "out"; // #27     at 0x0108
+    Utf8 "Ljava/io/PrintStream;"; // #28     at 0x010E
+    Utf8 "java/io/PrintStream"; // #29     at 0x0126
+    Utf8 "println"; // #30     at 0x013C
+    Utf8 "(Ljava/lang/String;)V"; // #31     at 0x0146
+  } // Constant Pool
+
+  0x0021; // access [ ACC_PUBLIC ACC_SUPER ]
+  #5;// this_cpx
+  #6;// super_cpx
+
+  [0] { // Interfaces
+  } // Interfaces
+
+  [0] { // fields
+  } // fields
+
+  [2] { // methods
+    { // Member at 0x016A
+      0x0001; // access
+      #7; // name_cpx
+      #8; // sig_cpx
+      [1] { // Attributes
+        Attr(#9, 29) { // Code at 0x0172
+          1; // max_stack
+          1; // max_locals
+          Bytes[5]{
+            0x2AB70001B1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 6) { // LineNumberTable at 0x0189
+              [1] { // LineNumberTable
+                0  1; //  at 0x0195
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+      } // Attributes
+    } // Member
+    ;
+    { // Member at 0x0195
+      0x0009; // access
+      #11; // name_cpx
+      #12; // sig_cpx
+      [2] { // Attributes
+        Attr(#9, 37) { // Code at 0x019D
+          2; // max_stack
+          1; // max_locals
+          Bytes[9]{
+            0xB200021203B60004;
+            0xB1;
+          };
+          [0] { // Traps
+          } // end Traps
+          [1] { // Attributes
+            Attr(#10, 10) { // LineNumberTable at 0x01B8
+              [2] { // LineNumberTable
+                0  4; //  at 0x01C4
+                8  5; //  at 0x01C8
+              }
+            } // end LineNumberTable
+          } // Attributes
+        } // end Code
+        ;
+        Attr(#13, 4) { // Exceptions at 0x01C8
+          [1] { // Exceptions
+            #14; //  at 0x01D2
+          }
+        } // end Exceptions
+      } // Attributes
+    } // Member
+  } // methods
+
+  [1] { // Attributes
+    Attr(#15, 2) { // SourceFile at 0x01D4
+      #16;
+    } // end SourceFile
+  } // Attributes
+} // end class BadMethodSig
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/verifier/TestSigParse.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8129579
+ * @summary Test that signatures are properly parsed when verification of local
+ *          classes is requested but verification of remote classes is not.
+ * @compile BadSignatures.jcod
+ * @run main/othervm -XX:+BytecodeVerificationLocal -XX:-BytecodeVerificationRemote TestSigParse
+ */
+
+public class TestSigParse {
+
+    public static void main(String args[]) throws Throwable {
+        System.out.println("Regression test for bug 819579");
+
+        // Test a FieldRef with a bad signature.
+        try {
+            Class newClass = Class.forName("BadFieldRef");
+            throw new RuntimeException("Expected ClasFormatError exception not thrown");
+        } catch (java.lang.ClassFormatError e) {
+            String eMsg = e.getMessage();
+            if (!eMsg.contains("Field") || !eMsg.contains("has illegal signature")) {
+                throw new RuntimeException("Unexpected exception: " + eMsg);
+            }
+        }
+
+        // Test a MethodRef with a bad signature.
+        try {
+            Class newClass = Class.forName("BadMethodRef");
+            throw new RuntimeException("Expected ClasFormatError exception not thrown");
+        } catch (java.lang.ClassFormatError e) {
+            String eMsg = e.getMessage();
+            if (!eMsg.contains("Method") || !eMsg.contains("has illegal signature")) {
+                throw new RuntimeException("Unexpected exception: " + eMsg);
+            }
+        }
+
+        // Test a method in a class with a bad signature.
+        try {
+            Class newClass = Class.forName("BadMethodSig");
+            throw new RuntimeException("Expected ClasFormatError exception not thrown");
+        } catch (java.lang.ClassFormatError e) {
+            String eMsg = e.getMessage();
+            if (!eMsg.contains("Class name contains illegal character")) {
+                throw new RuntimeException("Unexpected exception: " + eMsg);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/verifier/TestStaticIF.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8007736
+ * @summary Test static interface method.
+ * @run main/othervm -Xverify:all TestStaticIF
+ */
+
+public class TestStaticIF implements StaticMethodInInterface {
+
+    public static void main(String[] args) {
+        System.out.printf("main: %s%n", StaticMethodInInterface.get());
+    }
+}
+
+interface StaticMethodInInterface {
+
+    public static String get() {
+        return "Hello from StaticMethodInInterface.get()";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/verifier/VerifyProtectedConstructor.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/**
+ * @test
+
+ * @bug 6490436
+ * @summary Verify that protected constructor calls are not allowed for any classfile versions in either verifier.
+ * @author Keith McGuigan
+ */
+
+public class VerifyProtectedConstructor extends ClassLoader {
+  public static void main(String argv[]) throws Exception {
+    VerifyProtectedConstructor t = new VerifyProtectedConstructor();
+
+    t.loadSuperClass();
+
+    try {
+      t.checkClassVersion(49); // should not throw VerifyError
+      throw new Exception("FAIL: should be a VerifyError for CF version 49");
+    }
+    catch(VerifyError e) {
+       System.out.println("PASS for CF version 49");
+    }
+
+    try {
+      t.checkClassVersion(50); // should throw VerifyError
+      throw new Exception("FAIL: should be a VerifyError for CF version 50");
+    }
+    catch(VerifyError e) {
+       System.out.println("PASS");
+    }
+  }
+
+  private void loadSuperClass() {
+    /* -- code for super class A.A --
+       package A;
+       public class A {
+         protected A() {}
+       }
+    */
+    long[] cls_data = {
+      0xcafebabe00000032L, 0x000a0a0003000707L,
+      0x0008070009010006L, 0x3c696e69743e0100L,
+      0x0328295601000443L, 0x6f64650c00040005L,
+      0x010003412f410100L, 0x106a6176612f6c61L,
+      0x6e672f4f626a6563L, 0x7400210002000300L,
+      0x0000000001000400L, 0x0400050001000600L,
+      0x0000110001000100L, 0x0000052ab70001b1L,
+      0x0000000000000000L // 2 bytes extra
+    };
+    final int EXTRA = 2;
+    byte cf_bytes[] = toByteArray(cls_data);
+    defineClass("A.A", cf_bytes, 0, cf_bytes.length - EXTRA);
+  }
+
+  private int num_calls;
+  private static String classNames[] = { "B.B", "C.C" };
+
+  private void checkClassVersion(int version) throws VerifyError {
+    // This class is in violation of the spec since it accesses
+    // a protected constructor of a superclass while not being in the
+    // same package.
+    /* -- code for test class --
+        package B;
+        public class B extends A.A {
+          public static void f() { new A.A(); }
+        }
+    */
+    long[] cls_data = {
+      0xcafebabe00000032L, 0x000b0a0002000807L,
+      0x000907000a010006L, 0x3c696e69743e0100L,
+      0x0328295601000443L, 0x6f6465010001660cL,
+      0x0004000501000341L, 0x2f41010003422f42L,
+      0x0021000300020000L, 0x0000000200010004L,
+      0x0005000100060000L, 0x0011000100010000L,
+      0x00052ab70001b100L, 0x0000000009000700L,
+      0x0500010006000000L, 0x1500020000000000L,
+      0x09bb000259b70001L, 0x57b1000000000000L // no extra bytes
+    };
+    final int EXTRA = 0;
+
+    byte cf_bytes[] = toByteArray(cls_data);
+
+    // set version
+    cf_bytes[7] = (byte)version;
+
+    // Change B.B to C.C, D.D, ... for subsequent calls so we can call this
+    // multiple times and define different classes.
+    cf_bytes[61] += num_calls;
+    cf_bytes[63] += num_calls;
+    String name = classNames[num_calls];
+    num_calls++;
+
+    Class c = defineClass(name, cf_bytes, 0, cf_bytes.length - EXTRA);
+
+    try { c.newInstance(); } // to force linking, thus verification
+    catch(InstantiationException e) {}
+    catch(IllegalAccessException e) {}
+  }
+
+  static private byte[] toByteArray(long arr[]) {
+    // convert long array to byte array
+    java.nio.ByteBuffer bbuf = java.nio.ByteBuffer.allocate(arr.length * 8);
+    bbuf.asLongBuffer().put(java.nio.LongBuffer.wrap(arr));
+    return bbuf.array();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/verifier/VerifyStackForExceptionHandlers.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/**
+ * @test
+ * @bug 6547378
+ * @summary Verify that methods with max_stack==0 don't have exception handlers
+ * @author Keith McGuigan
+ */
+
+public class VerifyStackForExceptionHandlers extends ClassLoader {
+    public static void main(String argv[]) throws Exception {
+        VerifyStackForExceptionHandlers t =
+            new VerifyStackForExceptionHandlers();
+
+        try {
+            t.loadGoodClass();
+        } catch(VerifyError e) {
+            throw new Exception("FAIL: should be no VerifyError for class A");
+        }
+
+        try {
+            t.loadBadClass();
+            throw new Exception("FAIL: should be a VerifyError for class B");
+        } catch(VerifyError e) {
+            System.out.println("PASS");
+        }
+    }
+
+    private void loadGoodClass() {
+        /* -- code for class A --
+           public class A {
+               public static void f() {}
+           }
+        */
+        long[] cls_data = {
+            0xcafebabe00000031L, 0x000e0a0003000b07L,
+            0x000c07000d010006L, 0x3c696e69743e0100L,
+            0x0328295601000443L, 0x6f646501000f4c69L,
+            0x6e654e756d626572L, 0x5461626c65010001L,
+            0x6601000a536f7572L, 0x636546696c650100L,
+            0x06412e6a6176610cL, 0x0004000501000141L,
+            0x0100106a6176612fL, 0x6c616e672f4f626aL,
+            0x6563740021000200L, 0x0300000000000200L,
+            0x0100040005000100L, 0x060000001d000100L,
+            0x01000000052ab700L, 0x01b1000000010007L,
+            0x0000000600010000L, 0x0001000900080005L,
+            0x0001000600000019L, 0x0000000000000001L,
+            0xb100000001000700L, 0x0000060001000000L,
+            0x0200010009000000L, 0x02000a0000000000L
+        };
+        final int EXTRA = 5;
+
+        byte cf_bytes[] = toByteArray(cls_data);
+        Class c = defineClass("A", cf_bytes, 0, cf_bytes.length - EXTRA);
+
+        try { c.newInstance(); } // to force linking, thus verification
+        catch(InstantiationException e) {}
+        catch(IllegalAccessException e) {}
+    }
+
+    private void loadBadClass() throws VerifyError {
+        /* -- code for class B --
+           public class B {
+               public static void g() {}
+               public static void f() {
+                  // bytecode modified to have a max_stack value of 0
+                  try { g(); }
+                  catch (NullPointerException e) {}
+               }
+        }
+        */
+        long[] cls_data = {
+            0xcafebabe00000031L, 0x00120a000400060aL,
+            0x000d00030c000f00L, 0x0a0700050100106aL,
+            0x6176612f6c616e67L, 0x2f4f626a6563740cL,
+            0x0011000a01000a53L, 0x6f7572636546696cL,
+            0x6507000901001e6aL, 0x6176612f6c616e67L,
+            0x2f4e756c6c506f69L, 0x6e74657245786365L,
+            0x7074696f6e010003L, 0x282956010006422eL,
+            0x6a61736d01000443L, 0x6f646507000e0100L,
+            0x0142010001670100L, 0x01660100063c696eL,
+            0x69743e0021000d00L, 0x0400000000000300L,
+            0x010011000a000100L, 0x0c00000011000100L,
+            0x01000000052ab700L, 0x01b1000000000009L,
+            0x000f000a0001000cL, 0x0000000d00000000L,
+            0x00000001b1000000L, 0x0000090010000a00L,
+            0x01000c0000001c00L, 0x00000100000008b8L,
+            0x0002a700044bb100L, 0x0100000003000600L,
+            0x0800000001000700L, 0x000002000b000000L // 3 bytes extra
+
+        };
+        final int EXTRA = 3;
+
+        byte cf_bytes[] = toByteArray(cls_data);
+        Class c = defineClass("B", cf_bytes, 0, cf_bytes.length - EXTRA);
+
+        try { c.newInstance(); } // to force linking, thus verification
+        catch(InstantiationException e) {}
+        catch(IllegalAccessException e) {}
+    }
+
+    static private byte[] toByteArray(long arr[]) {
+        // convert long array to byte array
+        java.nio.ByteBuffer bbuf = java.nio.ByteBuffer.allocate(arr.length * 8);
+        bbuf.asLongBuffer().put(java.nio.LongBuffer.wrap(arr));
+        return bbuf.array();
+    }
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/verifier/defaultMethods/DefaultMethodRegressionTests.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8003639
+ * @summary defaultMethod resolution and verification
+ * @run main DefaultMethodRegressionTests
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This set of classes/interfaces (K/I/C) is specially designed to expose a
+ * bug in the JVM where it did not find some overloaded methods in some
+ * specific situations. (fixed by hotspot changeset ffb9316fd9ed).
+ */
+interface K {
+    int bbb(Long l);
+}
+
+interface I extends K {
+    default void aaa() {}
+    default void aab() {}
+    default void aac() {}
+
+    default int bbb(Integer i) { return 22; }
+    default int bbb(Float f) { return 33; }
+    default int bbb(Long l) { return 44; }
+    default int bbb(Double d) { return 55; }
+    default int bbb(String s) { return 66; }
+
+    default void caa() {}
+    default void cab() {}
+    default void cac() {}
+}
+
+class C implements I {}
+
+public class DefaultMethodRegressionTests {
+    public static void main(String... args) {
+        new DefaultMethodRegressionTests().run(args);
+    }
+    void run(String... args) {
+        testLostOverloadedMethod();
+        System.out.println("testLostOverloadedMethod: OK");
+        testInferenceVerifier();
+        System.out.println("testInferenceVerifier: OK");
+    }
+    void testLostOverloadedMethod() {
+        C c = new C();
+        assertEquals(c.bbb(new Integer(1)), 22);
+        assertEquals(c.bbb(new Float(1.1)), 33);
+        assertEquals(c.bbb(new Long(1L)), 44);
+        assertEquals(c.bbb(new Double(0.01)), 55);
+        assertEquals(c.bbb(new String("")), 66);
+    }
+    // Test to ensure that the inference verifier accepts older classfiles
+    // with classes that implement interfaces with defaults.
+    void testInferenceVerifier() {
+        // interface I { int m() default { return 99; } }
+        byte I_bytes[] = {
+            (byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, 0x00, 0x00, 0x00, 0x34,
+            0x00, 0x08, 0x07, 0x00, 0x06, 0x07, 0x00, 0x07,
+            0x01, 0x00, 0x03, 0x66, 0x6f, 0x6f, 0x01, 0x00,
+            0x03, 0x28, 0x29, 0x49, 0x01, 0x00, 0x04, 0x43,
+            0x6f, 0x64, 0x65, 0x01, 0x00, 0x01, 0x49, 0x01,
+            0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c,
+            0x61, 0x6e, 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65,
+            0x63, 0x74, 0x06, 0x00, 0x00, 0x01, 0x00, 0x02,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01,
+            0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x00, 0x05,
+            0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x01,
+            0x00, 0x00, 0x00, 0x03, 0x10, 0x63, (byte)0xac, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00
+        };
+        // public class C implements I {}  /* -target 1.5 */
+        byte C_bytes[] = {
+            (byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, 0x00, 0x00, 0x00, 0x31,
+            0x00, 0x0c, 0x0a, 0x00, 0x03, 0x00, 0x08, 0x07,
+            0x00, 0x09, 0x07, 0x00, 0x0a, 0x07, 0x00, 0x0b,
+            0x01, 0x00, 0x06, 0x3c, 0x69, 0x6e, 0x69, 0x74,
+            0x3e, 0x01, 0x00, 0x03, 0x28, 0x29, 0x56, 0x01,
+            0x00, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x0c, 0x00,
+            0x05, 0x00, 0x06, 0x01, 0x00, 0x01, 0x43, 0x01,
+            0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c,
+            0x61, 0x6e, 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65,
+            0x63, 0x74, 0x01, 0x00, 0x01, 0x49, 0x00, 0x21,
+            0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04,
+            0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x05,
+            0x00, 0x06, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00,
+            0x00, 0x11, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
+            0x00, 0x05, 0x2a, (byte)0xb7, 0x00, 0x01, (byte)0xb1, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00
+        };
+
+        ClassLoader cl = new ClassLoader() {
+            protected Class<?> findClass(String name) {
+                if (name.equals("I")) {
+                    return defineClass("I", I_bytes, 0, I_bytes.length);
+                } else if (name.equals("C")) {
+                    return defineClass("C", C_bytes, 0, C_bytes.length);
+                } else {
+                    return null;
+                }
+            }
+        };
+        try {
+            Class.forName("C", true, cl);
+        } catch (Exception e) {
+            // unmodified verifier will throw VerifyError
+            throw new RuntimeException(e);
+        }
+    }
+    void assertEquals(Object o1, Object o2) {
+        System.out.print("Expected: " + o1);
+        System.out.println(", Obtained: " + o2);
+        if (!o1.equals(o2)) {
+            throw new RuntimeException("got unexpected values");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/verifier/defaultMethods/DefaultMethodRegressionTestsRun.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8003639
+ * @summary defaultMethod resolution and verification using an URLClassLoader
+ * @modules jdk.compiler
+ *          jdk.zipfs
+ * @compile -XDignore.symbol.file=true DefaultMethodRegressionTestsRun.java
+ * @run main DefaultMethodRegressionTestsRun
+ */
+import java.io.File;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+/**
+ * This test is a variant of DefaultMethodRegressionTests, this one creates
+ * an URLClassLoader to load the support classes.
+ *
+ */
+public class DefaultMethodRegressionTestsRun {
+    public static void main(String... args) throws Exception {
+        File scratchDir = new File(".");
+        File testDir = new File(scratchDir, "testdir");
+        testDir.mkdirs();
+        File srcFile = new File(new File(System.getProperty("test.src")),
+                "DefaultMethodRegressionTests.java");
+        String[] javacargs = {
+            srcFile.getAbsolutePath(),
+            "-d",
+            testDir.getAbsolutePath()
+        };
+        com.sun.tools.javac.Main.compile(javacargs);
+        runClass(testDir, "DefaultMethodRegressionTests");
+    }
+    static void runClass(
+            File classPath,
+            String classname) throws Exception {
+        URL[] urls = {classPath.toURI().toURL()};
+        ClassLoader loader = new URLClassLoader(urls);
+        Class<?> c = loader.loadClass(classname);
+
+        Class<?>[] argTypes = new Class<?>[]{String[].class};
+        Object[] methodArgs = new Object[]{null};
+
+        Method method = c.getMethod("main", argTypes);
+        method.invoke(c, methodArgs);
+    }
+}
--- a/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.c	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1217 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2018, Google 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 <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "jvmti.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef JNI_ENV_ARG
-
-#ifdef __cplusplus
-#define JNI_ENV_ARG(x)
-#define JNI_ENV_ARG2(x, y) y
-#define JNI_ENV_ARG3(x, y, z) y, z
-#define JNI_ENV_ARG4(x, y, z, w) y, z, w
-#define JNI_ENV_PTR(x) x
-#else
-#define JNI_ENV_ARG(x) x
-#define JNI_ENV_ARG2(x, y) x, y
-#define JNI_ENV_ARG3(x, y, z) x, y, z
-#define JNI_ENV_ARG4(x, y, z, w) x, y, z, w
-#define JNI_ENV_PTR(x) (*x)
-#endif
-
-#endif
-
-#define TRUE 1
-#define FALSE 0
-#define PRINT_OUT 0
-
-static jvmtiEnv *jvmti = NULL;
-static jvmtiEnv *second_jvmti = NULL;
-
-typedef struct _ObjectTrace{
-  jweak object;
-  jlong size;
-  jvmtiFrameInfo* frames;
-  size_t frame_count;
-  jthread thread;
-} ObjectTrace;
-
-typedef struct _EventStorage {
-  int live_object_additions;
-  int live_object_size;
-  int live_object_count;
-  ObjectTrace** live_objects;
-
-  int garbage_history_size;
-  int garbage_history_index;
-  ObjectTrace** garbage_collected_objects;
-
-  // Two separate monitors to separate storage data race and the compaction field
-  // data race.
-  jrawMonitorID storage_monitor;
-
-  int compaction_required;
-  jrawMonitorID compaction_monitor;
-} EventStorage;
-
-typedef struct _ExpectedContentFrame {
-  const char *name;
-  const char *signature;
-  const char *file_name;
-  int line_number;
-} ExpectedContentFrame;
-
-static
-void event_storage_lock(EventStorage* storage) {
-  (*jvmti)->RawMonitorEnter(jvmti, storage->storage_monitor);
-}
-
-static
-void event_storage_unlock(EventStorage* storage) {
-  (*jvmti)->RawMonitorExit(jvmti, storage->storage_monitor);
-}
-
-static
-void event_storage_lock_compaction(EventStorage* storage) {
-  (*jvmti)->RawMonitorEnter(jvmti, storage->compaction_monitor);
-}
-
-static
-void event_storage_unlock_compaction(EventStorage* storage) {
-  (*jvmti)->RawMonitorExit(jvmti, storage->compaction_monitor);
-}
-
-// Given a method and a location, this method gets the line number.
-static
-jint get_line_number(jvmtiEnv* jvmti, jmethodID method,
-                     jlocation location) {
-  // Read the line number table.
-  jvmtiLineNumberEntry *table_ptr = 0;
-  jint line_number_table_entries;
-  int l;
-  jlocation last_location;
-  int jvmti_error = (*jvmti)->GetLineNumberTable(jvmti, method,
-                                                 &line_number_table_entries,
-                                                 &table_ptr);
-
-  if (JVMTI_ERROR_NONE != jvmti_error) {
-    return -1;
-  }
-  if (line_number_table_entries <= 0) {
-    return -1;
-  }
-  if (line_number_table_entries == 1) {
-    return table_ptr[0].line_number;
-  }
-
-  // Go through all the line numbers...
-  last_location = table_ptr[0].start_location;
-  for (l = 1; l < line_number_table_entries; l++) {
-    // ... and if you see one that is in the right place for your
-    // location, you've found the line number!
-    if ((location < table_ptr[l].start_location) &&
-        (location >= last_location)) {
-      return table_ptr[l - 1].line_number;
-    }
-    last_location = table_ptr[l].start_location;
-  }
-
-  if (location >= last_location) {
-    return table_ptr[line_number_table_entries - 1].line_number;
-  } else {
-    return -1;
-  }
-}
-
-static void print_out_frames(JNIEnv* env, ObjectTrace* trace) {
-  jvmtiFrameInfo* frames = trace->frames;
-  size_t i;
-  for (i = 0; i < trace->frame_count; i++) {
-    // Get basic information out of the trace.
-    jlocation bci = frames[i].location;
-    jmethodID methodid = frames[i].method;
-    char *name = NULL, *signature = NULL, *file_name = NULL;
-    jclass declaring_class;
-    int line_number;
-    jvmtiError err;
-
-    if (bci < 0) {
-      fprintf(stderr, "\tNative frame\n");
-      continue;
-    }
-
-    // Transform into usable information.
-    line_number = get_line_number(jvmti, methodid, bci);
-    if (JVMTI_ERROR_NONE !=
-        (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0)) {
-      fprintf(stderr, "\tUnknown method name\n");
-      continue;
-    }
-
-    if (JVMTI_ERROR_NONE !=
-        (*jvmti)->GetMethodDeclaringClass(jvmti, methodid, &declaring_class)) {
-      fprintf(stderr, "\tUnknown class\n");
-      continue;
-    }
-
-    err = (*jvmti)->GetSourceFileName(jvmti, declaring_class,
-                                      &file_name);
-    if (err != JVMTI_ERROR_NONE) {
-      fprintf(stderr, "\tUnknown file\n");
-      continue;
-    }
-
-    // Compare now, none should be NULL.
-    if (name == NULL) {
-      fprintf(stderr, "\tUnknown name\n");
-      continue;
-    }
-
-    if (file_name == NULL) {
-      fprintf(stderr, "\tUnknown file\n");
-      continue;
-    }
-
-    if (signature == NULL) {
-      fprintf(stderr, "\tUnknown signature\n");
-      continue;
-    }
-
-    fprintf(stderr, "\t%s%s (%s: %d)\n",
-            name, signature, file_name, line_number);
-  }
-}
-
-static jboolean check_sample_content(JNIEnv* env,
-                                     ObjectTrace* trace,
-                                     ExpectedContentFrame *expected,
-                                     size_t expected_count,
-                                     jboolean check_lines,
-                                     int print_out_comparisons) {
-  jvmtiFrameInfo* frames;
-  size_t i;
-
-  if (expected_count > trace->frame_count) {
-    return FALSE;
-  }
-
-  frames = trace->frames;
-  for (i = 0; i < expected_count; i++) {
-    // Get basic information out of the trace.
-    jlocation bci = frames[i].location;
-    jmethodID methodid = frames[i].method;
-    char *name = NULL, *signature = NULL, *file_name = NULL;
-    jclass declaring_class;
-    int line_number;
-    jboolean differ;
-    jvmtiError err;
-
-    if (bci < 0 && expected[i].line_number != -1) {
-      return FALSE;
-    }
-
-    // Transform into usable information.
-    line_number = get_line_number(jvmti, methodid, bci);
-    (*jvmti)->GetMethodName(jvmti, methodid, &name, &signature, 0);
-
-    if (JVMTI_ERROR_NONE !=
-        (*jvmti)->GetMethodDeclaringClass(jvmti, methodid, &declaring_class)) {
-      return FALSE;
-    }
-
-    err = (*jvmti)->GetSourceFileName(jvmti, declaring_class,
-                                      &file_name);
-    if (err != JVMTI_ERROR_NONE) {
-      return FALSE;
-    }
-
-    // Compare now, none should be NULL.
-    if (name == NULL) {
-      return FALSE;
-    }
-
-    if (file_name == NULL) {
-      return FALSE;
-    }
-
-    if (signature == NULL) {
-      return FALSE;
-    }
-
-    differ = (strcmp(name, expected[i].name) ||
-              strcmp(signature, expected[i].signature) ||
-              strcmp(file_name, expected[i].file_name) ||
-              (check_lines && line_number != expected[i].line_number));
-
-    if (print_out_comparisons) {
-      fprintf(stderr, "\tComparing: (check_lines: %d)\n", check_lines);
-      fprintf(stderr, "\t\tNames: %s and %s\n", name, expected[i].name);
-      fprintf(stderr, "\t\tSignatures: %s and %s\n", signature, expected[i].signature);
-      fprintf(stderr, "\t\tFile name: %s and %s\n", file_name, expected[i].file_name);
-      fprintf(stderr, "\t\tLines: %d and %d\n", line_number, expected[i].line_number);
-      fprintf(stderr, "\t\tResult is %d\n", differ);
-    }
-
-    if (differ) {
-      return FALSE;
-    }
-  }
-
-  return TRUE;
-}
-
-// Static native API for various tests.
-static int fill_native_frames(JNIEnv* env, jobjectArray frames,
-                              ExpectedContentFrame* native_frames, size_t size) {
-  size_t i;
-  for (i = 0; i < size; i++) {
-    jclass frame_class = NULL;
-    jfieldID line_number_field_id = 0;
-    int line_number = 0;
-    jfieldID string_id = 0;
-    jstring string_object = NULL;
-    const char* method = NULL;
-    const char* file_name = NULL;
-    const char* signature = NULL;
-
-    jobject obj = JNI_ENV_PTR(env)->GetObjectArrayElement(
-        JNI_ENV_ARG3(env, frames, (jsize) i));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in jni GetObjectArrayElement\n");
-      return -1;
-    }
-
-    frame_class = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG2(env, obj));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in jni GetObjectClass\n");
-      return -1;
-    }
-
-    line_number_field_id =
-        JNI_ENV_PTR(env)->GetFieldID(JNI_ENV_ARG4(env, frame_class, "lineNumber", "I"));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in jni GetFieldID\n");
-      return -1;
-    }
-
-    line_number = JNI_ENV_PTR(env)->GetIntField(JNI_ENV_ARG3(env, obj, line_number_field_id));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in jni GetIntField\n");
-      return -1;
-    }
-
-    string_id = JNI_ENV_PTR(env)->GetFieldID(
-        JNI_ENV_ARG4(env, frame_class, "method", "Ljava/lang/String;"));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in jni GetFieldID\n");
-      return -1;
-    }
-
-    string_object = (jstring) JNI_ENV_PTR(env)->GetObjectField(
-        JNI_ENV_ARG3(env, obj, string_id));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in jni GetObjectField\n");
-      return -1;
-    }
-
-    method = JNI_ENV_PTR(env)->GetStringUTFChars(JNI_ENV_ARG3(env, string_object, 0));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "Exception in jni GetStringUTFChars\n");
-      return -1;
-    }
-
-    string_id = JNI_ENV_PTR(env)->GetFieldID(
-        JNI_ENV_ARG4(env, frame_class, "fileName", "Ljava/lang/String;"));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "Exception in jni GetFieldID\n");
-      return -1;
-    }
-
-    string_object =
-        (jstring) (JNI_ENV_PTR(env)->GetObjectField(
-            JNI_ENV_ARG3(env, obj, string_id)));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in second jni GetObjectField\n");
-      return -1;
-    }
-
-    file_name = JNI_ENV_PTR(env)->GetStringUTFChars(
-        JNI_ENV_ARG3(env, string_object, 0));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in jni GetStringUTFChars\n");
-      return -1;
-    }
-
-    string_id = JNI_ENV_PTR(env)->GetFieldID(
-        JNI_ENV_ARG4(env, frame_class, "signature", "Ljava/lang/String;"));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in second jni GetFieldID\n");
-      return -1;
-    }
-
-    string_object =
-        (jstring) (JNI_ENV_PTR(env)->GetObjectField(
-            JNI_ENV_ARG3(env, obj, string_id)));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in third jni GetObjectField\n");
-      return -1;
-    }
-
-    signature = JNI_ENV_PTR(env)->GetStringUTFChars(
-        JNI_ENV_ARG3(env, string_object, 0));
-
-    if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-      fprintf(stderr, "fill_native_frames: Exception in jni GetStringUTFChars\n");
-      return -1;
-    }
-
-    native_frames[i].name = method;
-    native_frames[i].file_name = file_name;
-    native_frames[i].signature = signature;
-    native_frames[i].line_number = line_number;
-  }
-
-  return 0;
-}
-
-// Internal storage system implementation.
-static EventStorage global_event_storage;
-static EventStorage second_global_event_storage;
-
-static void event_storage_set_compaction_required(EventStorage* storage) {
-  event_storage_lock_compaction(storage);
-  storage->compaction_required = 1;
-  event_storage_unlock_compaction(storage);
-}
-
-static int event_storage_get_compaction_required(EventStorage* storage) {
-  int result;
-  event_storage_lock_compaction(storage);
-  result = storage->compaction_required;
-  event_storage_unlock_compaction(storage);
-  return result;
-}
-
-static void event_storage_set_garbage_history(EventStorage* storage, int value) {
-  size_t size;
-  event_storage_lock(storage);
-  global_event_storage.garbage_history_size = value;
-  free(global_event_storage.garbage_collected_objects);
-  size = sizeof(*global_event_storage.garbage_collected_objects) * value;
-  global_event_storage.garbage_collected_objects = malloc(size);
-  memset(global_event_storage.garbage_collected_objects, 0, size);
-  event_storage_unlock(storage);
-}
-
-// No mutex here, it is handled by the caller.
-static void event_storage_add_garbage_collected_object(EventStorage* storage,
-                                                       ObjectTrace* object) {
-  int idx = storage->garbage_history_index;
-  ObjectTrace* old_object = storage->garbage_collected_objects[idx];
-  if (old_object != NULL) {
-    free(old_object->frames);
-    free(storage->garbage_collected_objects[idx]);
-  }
-
-  storage->garbage_collected_objects[idx] = object;
-  storage->garbage_history_index = (idx + 1) % storage->garbage_history_size;
-}
-
-static int event_storage_get_count(EventStorage* storage) {
-  int result;
-  event_storage_lock(storage);
-  result = storage->live_object_count;
-  event_storage_unlock(storage);
-  return result;
-}
-
-static double event_storage_get_average_size(EventStorage* storage) {
-  double accumulation = 0;
-  int max_size;
-  int i;
-
-  event_storage_lock(storage);
-  max_size = storage->live_object_count;
-
-  for (i = 0; i < max_size; i++) {
-    accumulation += storage->live_objects[i]->size;
-  }
-
-  event_storage_unlock(storage);
-  return accumulation / max_size;
-}
-
-static jboolean event_storage_contains(JNIEnv* env,
-                                       EventStorage* storage,
-                                       ExpectedContentFrame* frames,
-                                       size_t size,
-                                       jboolean check_lines) {
-  int i;
-  event_storage_lock(storage);
-  fprintf(stderr, "Checking storage count %d\n", storage->live_object_count);
-  for (i = 0; i < storage->live_object_count; i++) {
-    ObjectTrace* trace = storage->live_objects[i];
-
-    if (check_sample_content(env, trace, frames, size, check_lines, PRINT_OUT)) {
-      event_storage_unlock(storage);
-      return TRUE;
-    }
-  }
-  event_storage_unlock(storage);
-  return FALSE;
-}
-
-static jlong event_storage_get_size(JNIEnv* env,
-                                    EventStorage* storage,
-                                    ExpectedContentFrame* frames,
-                                    size_t size,
-                                    jboolean check_lines) {
-  int i;
-  event_storage_lock(storage);
-  fprintf(stderr, "Getting element from storage count, size %d\n", storage->live_object_count);
-  for (i = 0; i < storage->live_object_count; i++) {
-    ObjectTrace* trace = storage->live_objects[i];
-
-    if (check_sample_content(env, trace, frames, size, check_lines, PRINT_OUT)) {
-      jlong result = trace->size;
-      event_storage_unlock(storage);
-      return result;
-    }
-  }
-  event_storage_unlock(storage);
-  return 0;
-}
-
-static jboolean event_storage_garbage_contains(JNIEnv* env,
-                                               EventStorage* storage,
-                                               ExpectedContentFrame* frames,
-                                               size_t size,
-                                               jboolean check_lines) {
-  int i;
-  event_storage_lock(storage);
-  fprintf(stderr, "Checking garbage storage count %d\n",
-          storage->garbage_history_size);
-  for (i = 0; i < storage->garbage_history_size; i++) {
-    ObjectTrace* trace = storage->garbage_collected_objects[i];
-
-    if (trace == NULL) {
-      continue;
-    }
-
-    if (check_sample_content(env, trace, frames, size, check_lines, PRINT_OUT)) {
-      event_storage_unlock(storage);
-      return TRUE;
-    }
-  }
-  event_storage_unlock(storage);
-  return FALSE;
-}
-
-// No mutex here, handled by the caller.
-static void event_storage_augment_storage(EventStorage* storage) {
-  int new_max = (storage->live_object_size * 2) + 1;
-  ObjectTrace** new_objects = malloc(new_max * sizeof(*new_objects));
-
-  int current_count = storage->live_object_count;
-  memcpy(new_objects, storage->live_objects, current_count * sizeof(*new_objects));
-  free(storage->live_objects);
-  storage->live_objects = new_objects;
-  storage->live_object_size = new_max;
-}
-
-static void event_storage_add(EventStorage* storage,
-                              JNIEnv* jni,
-                              jthread thread,
-                              jobject object,
-                              jclass klass,
-                              jlong size) {
-  jvmtiFrameInfo frames[64];
-  jint count;
-  jvmtiError err;
-
-  err = (*jvmti)->GetStackTrace(jvmti, thread, 0, 64, frames, &count);
-  if (err == JVMTI_ERROR_NONE && count >= 1) {
-    ObjectTrace* live_object;
-    jvmtiFrameInfo* allocated_frames = (jvmtiFrameInfo*) malloc(count * sizeof(*allocated_frames));
-    memcpy(allocated_frames, frames, count * sizeof(*allocated_frames));
-
-    live_object = (ObjectTrace*) malloc(sizeof(*live_object));
-    live_object->frames = allocated_frames;
-    live_object->frame_count = count;
-    live_object->size = size;
-    live_object->thread = thread;
-    live_object->object = (*jni)->NewWeakGlobalRef(jni, object);
-
-    if (JNI_ENV_PTR(jni)->ExceptionOccurred(JNI_ENV_ARG(jni))) {
-      JNI_ENV_PTR(jni)->FatalError(
-          JNI_ENV_ARG2(jni, "Error in event_storage_add: Exception in jni NewWeakGlobalRef"));
-    }
-
-    // Only now lock and get things done quickly.
-    event_storage_lock(storage);
-
-    storage->live_object_additions++;
-
-    if (storage->live_object_count >= storage->live_object_size) {
-      event_storage_augment_storage(storage);
-    }
-    assert(storage->live_object_count < storage->live_object_size);
-
-    if (PRINT_OUT) {
-      fprintf(stderr, "Adding trace for thread %p, frame_count %d, storage %p\n",
-              thread, count, storage);
-      print_out_frames(jni, live_object);
-    }
-    storage->live_objects[storage->live_object_count] = live_object;
-    storage->live_object_count++;
-
-    event_storage_unlock(storage);
-  }
-}
-
-static void event_storage_compact(EventStorage* storage, JNIEnv* jni) {
-  int max, i, dest;
-  ObjectTrace** live_objects;
-
-  event_storage_lock_compaction(storage);
-  storage->compaction_required = 0;
-  event_storage_unlock_compaction(storage);
-
-  event_storage_lock(storage);
-
-  max = storage->live_object_count;
-  live_objects = storage->live_objects;
-
-  for (i = 0, dest = 0; i < max; i++) {
-    ObjectTrace* live_object = live_objects[i];
-    jweak object = live_object->object;
-
-    if (!(*jni)->IsSameObject(jni, object, NULL)) {
-      if (dest != i) {
-        live_objects[dest] = live_object;
-        dest++;
-      }
-    } else {
-      (*jni)->DeleteWeakGlobalRef(jni, object);
-      live_object->object = NULL;
-
-      event_storage_add_garbage_collected_object(storage, live_object);
-    }
-  }
-
-  storage->live_object_count = dest;
-  event_storage_unlock(storage);
-}
-
-static void event_storage_free_objects(ObjectTrace** array, int max) {
-  int i;
-  for (i = 0; i < max; i++) {
-    free(array[i]), array[i] = NULL;
-  }
-}
-
-static void event_storage_reset(EventStorage* storage) {
-  event_storage_lock(storage);
-
-  // Reset everything except the mutex and the garbage collection.
-  event_storage_free_objects(storage->live_objects,
-                             storage->live_object_count);
-  storage->live_object_additions = 0;
-  storage->live_object_size = 0;
-  storage->live_object_count = 0;
-  free(storage->live_objects), storage->live_objects = NULL;
-
-  event_storage_free_objects(storage->garbage_collected_objects,
-                             storage->garbage_history_size);
-
-  storage->compaction_required = 0;
-  storage->garbage_history_index = 0;
-
-  event_storage_unlock(storage);
-}
-
-static int event_storage_number_additions(EventStorage* storage) {
-  int result;
-  event_storage_lock(storage);
-  result = storage->live_object_additions;
-  event_storage_unlock(storage);
-  return result;
-}
-
-// Start of the JVMTI agent code.
-static const char *EXC_CNAME = "java/lang/Exception";
-
-static int check_error(jvmtiError err, const char *s) {
-  if (err != JVMTI_ERROR_NONE) {
-    printf("  ## %s error: %d\n", s, err);
-    return 1;
-  }
-  return 0;
-}
-
-static int check_capability_error(jvmtiError err, const char *s) {
-  if (err != JVMTI_ERROR_NONE) {
-    if (err == JVMTI_ERROR_MUST_POSSESS_CAPABILITY) {
-      return 0;
-    }
-    fprintf(stderr, "  ## %s error: %d\n", s, err);
-  }
-  return 1;
-}
-
-static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
-
-JNIEXPORT
-jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
-  return Agent_Initialize(jvm, options, reserved);
-}
-
-JNIEXPORT
-jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
-  return Agent_Initialize(jvm, options, reserved);
-}
-
-JNIEXPORT
-jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
-  return JNI_VERSION_1_8;
-}
-
-#define MAX_THREADS 500
-
-typedef struct ThreadStats {
-  int thread_count;
-  int counts[MAX_THREADS];
-  char* threads[MAX_THREADS];
-} ThreadStats;
-
-static ThreadStats thread_stats;
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitorThreadDisabledTest_checkThreadSamplesOnlyFrom(
-    JNIEnv* env, jclass cls, jthread thread) {
-  jvmtiThreadInfo info;
-  jvmtiError err;
-  char* expected_name;
-  int found_thread = FALSE;
-
-  err = (*jvmti)->GetThreadInfo(jvmti, thread, &info);
-  expected_name = info.name;
-
-  if (err != JVMTI_ERROR_NONE) {
-    fprintf(stderr, "Failed to get thread information\n");
-    return FALSE;
-  }
-
-  if (thread_stats.thread_count != 1) {
-    fprintf(stderr, "Wrong thread number: %d (expected 1)\n",
-            thread_stats.thread_count);
-    return FALSE;
-  }
-
-  if (strcmp(expected_name, thread_stats.threads[0]) != 0) {
-    fprintf(stderr, "Unexpected thread name: '%s' (expected '%s')\n",
-            thread_stats.threads[0], expected_name);
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-static void add_thread_count(jthread thread) {
-  int i;
-  jvmtiThreadInfo info;
-  jvmtiError err;
-
-  err = (*jvmti)->GetThreadInfo(jvmti, thread, &info);
-  if (err != JVMTI_ERROR_NONE) {
-    fprintf(stderr, "Thread info for %p failed, ignoring thread count\n",
-            thread);
-    return;
-  }
-
-  event_storage_lock(&global_event_storage);
-  for (i = 0; i < thread_stats.thread_count; i++) {
-    if (!strcmp(thread_stats.threads[i], info.name)) {
-      thread_stats.counts[i]++;
-      event_storage_unlock(&global_event_storage);
-      return;
-    }
-  }
-
-  thread_stats.threads[thread_stats.thread_count] = info.name;
-  thread_stats.counts[thread_stats.thread_count]++;
-  thread_stats.thread_count++;
-  event_storage_unlock(&global_event_storage);
-}
-
-JNIEXPORT void JNICALL
-Java_MyPackage_HeapMonitorThreadDisabledTest_enableSamplingEvents(
-    JNIEnv* env, jclass cls, jthread thread) {
-  fprintf(stderr, "Enabling for %p\n", thread);
-  check_error((*jvmti)->SetEventNotificationMode(
-      jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, thread),
-              "Set event notifications for a single thread");
-}
-
-static void print_thread_stats() {
-  int i;
-  event_storage_lock(&global_event_storage);
-  fprintf(stderr, "Thread count:\n");
-  for (i = 0; i < thread_stats.thread_count; i++) {
-    fprintf(stderr, "\t%s: %d\n", thread_stats.threads[i], thread_stats.counts[i]);
-  }
-  event_storage_unlock(&global_event_storage);
-}
-
-JNIEXPORT
-void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env,
-                                JNIEnv* jni_env,
-                                jthread thread,
-                                jobject object,
-                                jclass object_klass,
-                                jlong size) {
-  add_thread_count(thread);
-
-  if (event_storage_get_compaction_required(&global_event_storage)) {
-    event_storage_compact(&global_event_storage, jni_env);
-  }
-
-  event_storage_add(&global_event_storage, jni_env, thread, object,
-                    object_klass, size);
-}
-
-JNIEXPORT
-void JNICALL VMObjectAlloc(jvmtiEnv *jvmti_env,
-                           JNIEnv* jni_env,
-                           jthread thread,
-                           jobject object,
-                           jclass object_klass,
-                           jlong size) {
-  event_storage_add(&second_global_event_storage, jni_env, thread, object,
-                    object_klass, size);
-}
-
-JNIEXPORT
-void JNICALL GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
-  event_storage_set_compaction_required(&global_event_storage);
-}
-
-static int enable_notifications() {
-  if (check_error((*jvmti)->SetEventNotificationMode(
-      jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
-                     "Set event notifications")) {
-    return 1;
-  }
-
-  return check_error((*jvmti)->SetEventNotificationMode(
-      jvmti, JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
-                     "Set event notifications");
-}
-
-static
-jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
-  jint res;
-  jvmtiEventCallbacks callbacks;
-  jvmtiCapabilities caps;
-
-  res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG3(jvm, (void **) &jvmti,
-                                 JVMTI_VERSION_9));
-  if (res != JNI_OK || jvmti == NULL) {
-    fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
-    return JNI_ERR;
-  }
-
-  // Get second jvmti environment.
-  res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG3(jvm, (void **) &second_jvmti,
-                                 JVMTI_VERSION_9));
-  if (res != JNI_OK || second_jvmti == NULL) {
-    fprintf(stderr, "Error: wrong result of a valid second call to GetEnv!\n");
-    return JNI_ERR;
-  }
-
-  if (PRINT_OUT) {
-    fprintf(stderr, "Storage is at %p, secondary is at %p\n",
-            &global_event_storage, &second_global_event_storage);
-  }
-
-  (*jvmti)->CreateRawMonitor(jvmti, "storage_monitor",
-                             &global_event_storage.storage_monitor);
-  (*jvmti)->CreateRawMonitor(jvmti, "second_storage_monitor",
-                             &second_global_event_storage.storage_monitor);
-
-  (*jvmti)->CreateRawMonitor(jvmti, "compaction_monitor",
-                             &global_event_storage.compaction_monitor);
-  (*jvmti)->CreateRawMonitor(jvmti, "second_compaction_monitor",
-                             &second_global_event_storage.compaction_monitor);
-
-  event_storage_set_garbage_history(&global_event_storage, 200);
-  event_storage_set_garbage_history(&second_global_event_storage, 200);
-
-  memset(&callbacks, 0, sizeof(callbacks));
-  callbacks.SampledObjectAlloc = &SampledObjectAlloc;
-  callbacks.VMObjectAlloc = &VMObjectAlloc;
-  callbacks.GarbageCollectionFinish = &GarbageCollectionFinish;
-
-  memset(&caps, 0, sizeof(caps));
-  // Get line numbers, sample events, filename, and gc events for the tests.
-  caps.can_get_line_numbers = 1;
-  caps.can_get_source_file_name = 1;
-  caps.can_generate_garbage_collection_events = 1;
-  caps.can_generate_sampled_object_alloc_events = 1;
-  caps.can_generate_vm_object_alloc_events = 1;
-  if (check_error((*jvmti)->AddCapabilities(jvmti, &caps), "Add capabilities")) {
-    return JNI_ERR;
-  }
-
-  if (check_error((*jvmti)->SetEventCallbacks(jvmti, &callbacks,
-                                              sizeof(jvmtiEventCallbacks)),
-                  " Set Event Callbacks")) {
-    return JNI_ERR;
-  }
-  return JNI_OK;
-}
-
-JNIEXPORT void JNICALL
-Java_MyPackage_HeapMonitor_setSamplingInterval(JNIEnv* env, jclass cls, jint value) {
-  (*jvmti)->SetHeapSamplingInterval(jvmti, value);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitor_eventStorageIsEmpty(JNIEnv* env, jclass cls) {
-  return event_storage_get_count(&global_event_storage) == 0;
-}
-
-JNIEXPORT jint JNICALL
-Java_MyPackage_HeapMonitor_getEventStorageElementCount(JNIEnv* env, jclass cls) {
-  return event_storage_get_count(&global_event_storage);
-}
-
-JNIEXPORT void JNICALL
-Java_MyPackage_HeapMonitor_enableSamplingEvents(JNIEnv* env, jclass cls) {
-  enable_notifications();
-}
-
-JNIEXPORT void JNICALL
-Java_MyPackage_HeapMonitor_disableSamplingEvents(JNIEnv* env, jclass cls) {
-  check_error((*jvmti)->SetEventNotificationMode(
-      jvmti, JVMTI_DISABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
-              "Set event notifications");
-
-  check_error((*jvmti)->SetEventNotificationMode(
-      jvmti, JVMTI_DISABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
-              "Garbage Collection Finish");
-}
-
-static ExpectedContentFrame *get_native_frames(JNIEnv* env, jclass cls,
-                                               jobjectArray frames) {
-  ExpectedContentFrame *native_frames;
-  jsize size = JNI_ENV_PTR(env)->GetArrayLength(JNI_ENV_ARG2(env, frames));
-
-  if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env))) {
-    JNI_ENV_PTR(env)->FatalError(
-        JNI_ENV_ARG2(env, "get_native_frames failed with the GetArrayLength call"));
-  }
-
-  native_frames = malloc(size * sizeof(*native_frames));
-
-  if (native_frames == NULL) {
-    JNI_ENV_PTR(env)->FatalError(
-        JNI_ENV_ARG2(env,
-                     "Error in get_native_frames: malloc returned NULL\n"));
-  }
-
-  if (fill_native_frames(env, frames, native_frames, size) != 0) {
-    JNI_ENV_PTR(env)->FatalError(
-        JNI_ENV_ARG2(env,
-                     "Error in get_native_frames: fill_native_frames returned failed status\n"));
-  }
-
-  return native_frames;
-}
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitor_obtainedEvents(JNIEnv* env, jclass cls,
-                                          jobjectArray frames,
-                                          jboolean check_lines) {
-  jboolean result;
-  jsize size = JNI_ENV_PTR(env)->GetArrayLength(JNI_ENV_ARG2(env, frames));
-  ExpectedContentFrame *native_frames = get_native_frames(env, cls, frames);
-
-  result = event_storage_contains(env, &global_event_storage, native_frames,
-                                  size, check_lines);
-
-  free(native_frames), native_frames = NULL;
-  return result;
-}
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitor_garbageContains(JNIEnv* env, jclass cls,
-                                           jobjectArray frames,
-                                           jboolean check_lines) {
-  jboolean result;
-  jsize size = JNI_ENV_PTR(env)->GetArrayLength(JNI_ENV_ARG2(env, frames));
-  ExpectedContentFrame *native_frames = get_native_frames(env, cls, frames);
-
-  result = event_storage_garbage_contains(env, &global_event_storage,
-                                          native_frames, size, check_lines);
-
-  free(native_frames), native_frames = NULL;
-  return result;
-}
-
-JNIEXPORT jlong JNICALL
-Java_MyPackage_HeapMonitor_getSize(JNIEnv* env, jclass cls,
-                                   jobjectArray frames,
-                                   jboolean check_lines) {
-  jlong result = 0;
-  jsize size = JNI_ENV_PTR(env)->GetArrayLength(JNI_ENV_ARG2(env, frames));
-  ExpectedContentFrame *native_frames = get_native_frames(env, cls, frames);
-
-  result = event_storage_get_size(env, &global_event_storage,
-                                  native_frames, size, check_lines);
-
-  free(native_frames), native_frames = NULL;
-  return result;
-}
-
-JNIEXPORT void JNICALL
-Java_MyPackage_HeapMonitor_forceGarbageCollection(JNIEnv* env, jclass cls) {
-  check_error((*jvmti)->ForceGarbageCollection(jvmti),
-              "Forced Garbage Collection");
-}
-
-JNIEXPORT void JNICALL
-Java_MyPackage_HeapMonitor_resetEventStorage(JNIEnv* env, jclass cls) {
-  event_storage_reset(&global_event_storage);
-  event_storage_reset(&second_global_event_storage);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitorNoCapabilityTest_allSamplingMethodsFail(JNIEnv *env,
-                                                                  jclass cls) {
-  jvmtiCapabilities caps;
-  memset(&caps, 0, sizeof(caps));
-  caps.can_generate_sampled_object_alloc_events = 1;
-  if (check_error((*jvmti)->RelinquishCapabilities(jvmti, &caps),
-                  "Add capabilities\n")){
-    return FALSE;
-  }
-
-  if (check_capability_error((*jvmti)->SetHeapSamplingInterval(jvmti, 1<<19),
-                             "Set Heap Sampling Interval")) {
-    return FALSE;
-  }
-  return TRUE;
-}
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitorIllegalArgumentTest_testIllegalArgument(JNIEnv *env,
-                                                                  jclass cls) {
-  if (check_error((*jvmti)->SetHeapSamplingInterval(jvmti, 0),
-                  "Sampling interval 0 failed\n")){
-    return FALSE;
-  }
-
-  if (check_error((*jvmti)->SetHeapSamplingInterval(jvmti, 1024),
-                  "Sampling interval 1024 failed\n")){
-    return FALSE;
-  }
-
-  if (!check_error((*jvmti)->SetHeapSamplingInterval(jvmti, -1),
-                   "Sampling interval -1 passed\n")){
-    return FALSE;
-  }
-
-  if (!check_error((*jvmti)->SetHeapSamplingInterval(jvmti, -1024),
-                   "Sampling interval -1024 passed\n")){
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-JNIEXPORT jdouble JNICALL
-Java_MyPackage_HeapMonitor_getAverageSize(JNIEnv *env, jclass cls) {
-  return event_storage_get_average_size(&global_event_storage);
-}
-
-typedef struct sThreadsFound {
-  jthread* threads;
-  int num_threads;
-} ThreadsFound;
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitorThreadTest_checkSamples(JNIEnv* env, jclass cls,
-                                                  jint num_threads) {
-  print_thread_stats();
-  // Ensure we got stacks from at least num_threads.
-  return thread_stats.thread_count >= num_threads;
-}
-
-JNIEXPORT
-void JNICALL SampledObjectAlloc2(jvmtiEnv *jvmti_env,
-                                 JNIEnv* jni_env,
-                                 jthread thread,
-                                 jobject object,
-                                 jclass object_klass,
-                                 jlong size) {
-  // Nop for now, two agents are not yet implemented.
-  assert(0);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitorTwoAgentsTest_enablingSamplingInSecondaryAgent(
-    JNIEnv* env, jclass cls) {
-  // Currently this method should be failing directly at the AddCapability step
-  // but the implementation is correct for when multi-agent support is enabled.
-  jvmtiCapabilities caps;
-  jvmtiEventCallbacks callbacks;
-
-  memset(&caps, 0, sizeof(caps));
-  caps.can_generate_sampled_object_alloc_events = 1;
-  if (check_error((*second_jvmti)->AddCapabilities(second_jvmti, &caps),
-                  "Set the capability for second agent")) {
-    return FALSE;
-  }
-
-  memset(&callbacks, 0, sizeof(callbacks));
-  callbacks.SampledObjectAlloc = &SampledObjectAlloc2;
-
-  if (check_error((*second_jvmti)->SetEventCallbacks(second_jvmti, &callbacks,
-                                                     sizeof(jvmtiEventCallbacks)),
-                  " Set Event Callbacks for second agent")) {
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-JNIEXPORT void JNICALL
-Java_MyPackage_HeapMonitor_enableVMEvents(JNIEnv* env, jclass cls) {
-  check_error((*jvmti)->SetEventNotificationMode(
-      jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL),
-              "Set vm event notifications");
-}
-
-JNIEXPORT jint JNICALL
-Java_MyPackage_HeapMonitorVMEventsTest_vmEvents(JNIEnv* env, jclass cls) {
-  return event_storage_number_additions(&second_global_event_storage);
-}
-
-JNIEXPORT jint JNICALL
-Java_MyPackage_HeapMonitor_sampledEvents(JNIEnv* env, jclass cls) {
-  return event_storage_number_additions(&global_event_storage);
-}
-
-static jobject allocate_object(JNIEnv* env) {
-  // Construct an Object.
-  jclass cls = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG2(env, "java/lang/Object"));
-  jmethodID constructor;
-  jobject result;
-
-  if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env)) || cls == NULL) {
-    JNI_ENV_PTR(env)->FatalError(
-        JNI_ENV_ARG2(env, "Error in jni FindClass: Cannot find Object class\n"));
-  }
-
-  constructor = JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG4(env, cls, "<init>", "()V"));
-  if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env)) || constructor == NULL) {
-    JNI_ENV_PTR(env)->FatalError(
-        JNI_ENV_ARG2(env, "Error in jni GetMethodID: Cannot find Object class constructor\n"));
-  }
-
-  // Call back constructor to allocate a new instance, with an int argument
-  result = JNI_ENV_PTR(env)->NewObject(JNI_ENV_ARG3(env, cls, constructor));
-
-  if (JNI_ENV_PTR(env)->ExceptionOccurred(JNI_ENV_ARG(env)) || result == NULL) {
-    JNI_ENV_PTR(env)->FatalError(
-        JNI_ENV_ARG2(env, "Error in jni NewObject: Cannot allocate an object\n"));
-  }
-  return result;
-}
-
-// Ensure we got a callback for the test.
-static int did_recursive_callback_test;
-
-JNIEXPORT
-void JNICALL RecursiveSampledObjectAlloc(jvmtiEnv *jvmti_env,
-                                         JNIEnv* jni_env,
-                                         jthread thread,
-                                         jobject object,
-                                         jclass object_klass,
-                                         jlong size) {
-  // Basically ensure that if we were to allocate objects, we would not have an
-  // infinite recursion here.
-  int i;
-  for (i = 0; i < 1000; i++) {
-    if (allocate_object(jni_env) == NULL) {
-      JNI_ENV_PTR(jni_env)->FatalError(JNI_ENV_ARG2(jni_env, "allocate_object returned NULL\n"));
-    }
-  }
-
-  did_recursive_callback_test = 1;
-}
-
-JNIEXPORT jboolean JNICALL
-Java_MyPackage_HeapMonitorRecursiveTest_didCallback(JNIEnv* env, jclass cls) {
-  return did_recursive_callback_test != 0;
-}
-
-JNIEXPORT void JNICALL
-Java_MyPackage_HeapMonitorRecursiveTest_setCallbackToCallAllocateSomeMore(JNIEnv* env, jclass cls) {
-  jvmtiEventCallbacks callbacks;
-
-  memset(&callbacks, 0, sizeof(callbacks));
-  callbacks.SampledObjectAlloc = &RecursiveSampledObjectAlloc;
-
-  if (check_error((*jvmti)->SetEventCallbacks(jvmti, &callbacks,
-                                              sizeof(jvmtiEventCallbacks)),
-                  " Set Event Callbacks")) {
-    JNI_ENV_PTR(env)->FatalError(JNI_ENV_ARG2(env, "Cannot reset the callback."));
-  }
-}
-
-#ifdef __cplusplus
-}
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/libHeapMonitorTest.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,1165 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Google 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 <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jvmti.h"
+
+extern "C" {
+
+#define TRUE 1
+#define FALSE 0
+#define PRINT_OUT 0
+
+static jvmtiEnv *jvmti = NULL;
+static jvmtiEnv *second_jvmti = NULL;
+
+typedef struct _ObjectTrace{
+  jweak object;
+  jlong size;
+  jvmtiFrameInfo* frames;
+  size_t frame_count;
+  jthread thread;
+} ObjectTrace;
+
+typedef struct _EventStorage {
+  int live_object_additions;
+  int live_object_size;
+  int live_object_count;
+  ObjectTrace** live_objects;
+
+  int garbage_history_size;
+  int garbage_history_index;
+  ObjectTrace** garbage_collected_objects;
+
+  // Two separate monitors to separate storage data race and the compaction field
+  // data race.
+  jrawMonitorID storage_monitor;
+
+  int compaction_required;
+  jrawMonitorID compaction_monitor;
+} EventStorage;
+
+typedef struct _ExpectedContentFrame {
+  const char *name;
+  const char *signature;
+  const char *file_name;
+  int line_number;
+} ExpectedContentFrame;
+
+static
+void event_storage_lock(EventStorage* storage) {
+  jvmti->RawMonitorEnter(storage->storage_monitor);
+}
+
+static
+void event_storage_unlock(EventStorage* storage) {
+  jvmti->RawMonitorExit(storage->storage_monitor);
+}
+
+static
+void event_storage_lock_compaction(EventStorage* storage) {
+  jvmti->RawMonitorEnter(storage->compaction_monitor);
+}
+
+static
+void event_storage_unlock_compaction(EventStorage* storage) {
+  jvmti->RawMonitorExit(storage->compaction_monitor);
+}
+
+// Given a method and a location, this method gets the line number.
+static
+jint get_line_number(jmethodID method, jlocation location) {
+  // Read the line number table.
+  jvmtiLineNumberEntry *table_ptr = 0;
+  jint line_number_table_entries;
+  int l;
+  jlocation last_location;
+  int jvmti_error = jvmti->GetLineNumberTable(method,
+                                              &line_number_table_entries,
+                                              &table_ptr);
+
+  if (JVMTI_ERROR_NONE != jvmti_error) {
+    return -1;
+  }
+  if (line_number_table_entries <= 0) {
+    return -1;
+  }
+  if (line_number_table_entries == 1) {
+    return table_ptr[0].line_number;
+  }
+
+  // Go through all the line numbers...
+  last_location = table_ptr[0].start_location;
+  for (l = 1; l < line_number_table_entries; l++) {
+    // ... and if you see one that is in the right place for your
+    // location, you've found the line number!
+    if ((location < table_ptr[l].start_location) &&
+        (location >= last_location)) {
+      return table_ptr[l - 1].line_number;
+    }
+    last_location = table_ptr[l].start_location;
+  }
+
+  if (location >= last_location) {
+    return table_ptr[line_number_table_entries - 1].line_number;
+  } else {
+    return -1;
+  }
+}
+
+static void print_out_frames(JNIEnv* env, ObjectTrace* trace) {
+  jvmtiFrameInfo* frames = trace->frames;
+  size_t i;
+  for (i = 0; i < trace->frame_count; i++) {
+    // Get basic information out of the trace.
+    jlocation bci = frames[i].location;
+    jmethodID methodid = frames[i].method;
+    char *name = NULL, *signature = NULL, *file_name = NULL;
+    jclass declaring_class;
+    int line_number;
+    jvmtiError err;
+
+    if (bci < 0) {
+      fprintf(stderr, "\tNative frame\n");
+      continue;
+    }
+
+    // Transform into usable information.
+    line_number = get_line_number(methodid, bci);
+    if (JVMTI_ERROR_NONE != jvmti->GetMethodName(methodid, &name, &signature, 0)) {
+      fprintf(stderr, "\tUnknown method name\n");
+      continue;
+    }
+
+    if (JVMTI_ERROR_NONE != jvmti->GetMethodDeclaringClass(methodid, &declaring_class)) {
+      fprintf(stderr, "\tUnknown class\n");
+      continue;
+    }
+
+    err = jvmti->GetSourceFileName(declaring_class, &file_name);
+    if (err != JVMTI_ERROR_NONE) {
+      fprintf(stderr, "\tUnknown file\n");
+      continue;
+    }
+
+    // Compare now, none should be NULL.
+    if (name == NULL) {
+      fprintf(stderr, "\tUnknown name\n");
+      continue;
+    }
+
+    if (file_name == NULL) {
+      fprintf(stderr, "\tUnknown file\n");
+      continue;
+    }
+
+    if (signature == NULL) {
+      fprintf(stderr, "\tUnknown signature\n");
+      continue;
+    }
+
+    fprintf(stderr, "\t%s%s (%s: %d)\n", name, signature, file_name, line_number);
+  }
+}
+
+static jboolean check_sample_content(JNIEnv* env,
+                                     ObjectTrace* trace,
+                                     ExpectedContentFrame *expected,
+                                     size_t expected_count,
+                                     jboolean check_lines,
+                                     int print_out_comparisons) {
+  jvmtiFrameInfo* frames;
+  size_t i;
+
+  if (expected_count > trace->frame_count) {
+    return FALSE;
+  }
+
+  frames = trace->frames;
+  for (i = 0; i < expected_count; i++) {
+    // Get basic information out of the trace.
+    jlocation bci = frames[i].location;
+    jmethodID methodid = frames[i].method;
+    char *name = NULL, *signature = NULL, *file_name = NULL;
+    jclass declaring_class;
+    int line_number;
+    jboolean differ;
+    jvmtiError err;
+
+    if (bci < 0 && expected[i].line_number != -1) {
+      return FALSE;
+    }
+
+    // Transform into usable information.
+    line_number = get_line_number(methodid, bci);
+    jvmti->GetMethodName(methodid, &name, &signature, 0);
+
+    if (JVMTI_ERROR_NONE != jvmti->GetMethodDeclaringClass(methodid, &declaring_class)) {
+      return FALSE;
+    }
+
+    err = jvmti->GetSourceFileName(declaring_class, &file_name);
+    if (err != JVMTI_ERROR_NONE) {
+      return FALSE;
+    }
+
+    // Compare now, none should be NULL.
+    if (name == NULL) {
+      return FALSE;
+    }
+
+    if (file_name == NULL) {
+      return FALSE;
+    }
+
+    if (signature == NULL) {
+      return FALSE;
+    }
+
+    differ = (strcmp(name, expected[i].name) ||
+              strcmp(signature, expected[i].signature) ||
+              strcmp(file_name, expected[i].file_name) ||
+              (check_lines && line_number != expected[i].line_number));
+
+    if (print_out_comparisons) {
+      fprintf(stderr, "\tComparing: (check_lines: %d)\n", check_lines);
+      fprintf(stderr, "\t\tNames: %s and %s\n", name, expected[i].name);
+      fprintf(stderr, "\t\tSignatures: %s and %s\n", signature, expected[i].signature);
+      fprintf(stderr, "\t\tFile name: %s and %s\n", file_name, expected[i].file_name);
+      fprintf(stderr, "\t\tLines: %d and %d\n", line_number, expected[i].line_number);
+      fprintf(stderr, "\t\tResult is %d\n", differ);
+    }
+
+    if (differ) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+// Static native API for various tests.
+static int fill_native_frames(JNIEnv* env, jobjectArray frames,
+                              ExpectedContentFrame* native_frames, size_t size) {
+  size_t i;
+  for (i = 0; i < size; i++) {
+    jclass frame_class = NULL;
+    jfieldID line_number_field_id = 0;
+    int line_number = 0;
+    jfieldID string_id = 0;
+    jstring string_object = NULL;
+    const char* method = NULL;
+    const char* file_name = NULL;
+    const char* signature = NULL;
+
+    jobject obj = env->GetObjectArrayElement(frames, (jsize) i);
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in jni GetObjectArrayElement\n");
+      return -1;
+    }
+
+    frame_class = env->GetObjectClass(obj);
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in jni GetObjectClass\n");
+      return -1;
+    }
+
+    line_number_field_id = env->GetFieldID(frame_class, "lineNumber", "I");
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in jni GetFieldID\n");
+      return -1;
+    }
+
+    line_number = env->GetIntField(obj, line_number_field_id);
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in jni GetIntField\n");
+      return -1;
+    }
+
+    string_id = env->GetFieldID(frame_class, "method", "Ljava/lang/String;");
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in jni GetFieldID\n");
+      return -1;
+    }
+
+    string_object = (jstring) env->GetObjectField(obj, string_id);
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in jni GetObjectField\n");
+      return -1;
+    }
+
+    method = env->GetStringUTFChars(string_object, 0);
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "Exception in jni GetStringUTFChars\n");
+      return -1;
+    }
+
+    string_id = env->GetFieldID(frame_class, "fileName", "Ljava/lang/String;");
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "Exception in jni GetFieldID\n");
+      return -1;
+    }
+
+    string_object = (jstring) (env->GetObjectField(obj, string_id));
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in second jni GetObjectField\n");
+      return -1;
+    }
+
+    file_name = env->GetStringUTFChars(string_object, 0);
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in jni GetStringUTFChars\n");
+      return -1;
+    }
+
+    string_id = env->GetFieldID(frame_class, "signature", "Ljava/lang/String;");
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in second jni GetFieldID\n");
+      return -1;
+    }
+
+    string_object = (jstring) (env->GetObjectField(obj, string_id));
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in third jni GetObjectField\n");
+      return -1;
+    }
+
+    signature = env->GetStringUTFChars(string_object, 0);
+
+    if (env->ExceptionOccurred()) {
+      fprintf(stderr, "fill_native_frames: Exception in jni GetStringUTFChars\n");
+      return -1;
+    }
+
+    native_frames[i].name = method;
+    native_frames[i].file_name = file_name;
+    native_frames[i].signature = signature;
+    native_frames[i].line_number = line_number;
+  }
+
+  return 0;
+}
+
+// Internal storage system implementation.
+static EventStorage global_event_storage;
+static EventStorage second_global_event_storage;
+
+static void event_storage_set_compaction_required(EventStorage* storage) {
+  event_storage_lock_compaction(storage);
+  storage->compaction_required = 1;
+  event_storage_unlock_compaction(storage);
+}
+
+static int event_storage_get_compaction_required(EventStorage* storage) {
+  int result;
+  event_storage_lock_compaction(storage);
+  result = storage->compaction_required;
+  event_storage_unlock_compaction(storage);
+  return result;
+}
+
+static void event_storage_set_garbage_history(EventStorage* storage, int value) {
+  size_t size;
+  event_storage_lock(storage);
+  global_event_storage.garbage_history_size = value;
+  free(global_event_storage.garbage_collected_objects);
+  size = sizeof(*global_event_storage.garbage_collected_objects) * value;
+  global_event_storage.garbage_collected_objects = reinterpret_cast<ObjectTrace**>(malloc(size));
+  memset(global_event_storage.garbage_collected_objects, 0, size);
+  event_storage_unlock(storage);
+}
+
+// No mutex here, it is handled by the caller.
+static void event_storage_add_garbage_collected_object(EventStorage* storage,
+                                                       ObjectTrace* object) {
+  int idx = storage->garbage_history_index;
+  ObjectTrace* old_object = storage->garbage_collected_objects[idx];
+  if (old_object != NULL) {
+    free(old_object->frames);
+    free(storage->garbage_collected_objects[idx]);
+  }
+
+  storage->garbage_collected_objects[idx] = object;
+  storage->garbage_history_index = (idx + 1) % storage->garbage_history_size;
+}
+
+static int event_storage_get_count(EventStorage* storage) {
+  int result;
+  event_storage_lock(storage);
+  result = storage->live_object_count;
+  event_storage_unlock(storage);
+  return result;
+}
+
+static double event_storage_get_average_size(EventStorage* storage) {
+  double accumulation = 0;
+  int max_size;
+  int i;
+
+  event_storage_lock(storage);
+  max_size = storage->live_object_count;
+
+  for (i = 0; i < max_size; i++) {
+    accumulation += storage->live_objects[i]->size;
+  }
+
+  event_storage_unlock(storage);
+  return accumulation / max_size;
+}
+
+static jboolean event_storage_contains(JNIEnv* env,
+                                       EventStorage* storage,
+                                       ExpectedContentFrame* frames,
+                                       size_t size,
+                                       jboolean check_lines) {
+  int i;
+  event_storage_lock(storage);
+  fprintf(stderr, "Checking storage count %d\n", storage->live_object_count);
+  for (i = 0; i < storage->live_object_count; i++) {
+    ObjectTrace* trace = storage->live_objects[i];
+
+    if (check_sample_content(env, trace, frames, size, check_lines, PRINT_OUT)) {
+      event_storage_unlock(storage);
+      return TRUE;
+    }
+  }
+  event_storage_unlock(storage);
+  return FALSE;
+}
+
+static jlong event_storage_get_size(JNIEnv* env,
+                                    EventStorage* storage,
+                                    ExpectedContentFrame* frames,
+                                    size_t size,
+                                    jboolean check_lines) {
+  int i;
+  event_storage_lock(storage);
+  fprintf(stderr, "Getting element from storage count, size %d\n", storage->live_object_count);
+  for (i = 0; i < storage->live_object_count; i++) {
+    ObjectTrace* trace = storage->live_objects[i];
+
+    if (check_sample_content(env, trace, frames, size, check_lines, PRINT_OUT)) {
+      jlong result = trace->size;
+      event_storage_unlock(storage);
+      return result;
+    }
+  }
+  event_storage_unlock(storage);
+  return 0;
+}
+
+static jboolean event_storage_garbage_contains(JNIEnv* env,
+                                               EventStorage* storage,
+                                               ExpectedContentFrame* frames,
+                                               size_t size,
+                                               jboolean check_lines) {
+  int i;
+  event_storage_lock(storage);
+  fprintf(stderr, "Checking garbage storage count %d\n",
+          storage->garbage_history_size);
+  for (i = 0; i < storage->garbage_history_size; i++) {
+    ObjectTrace* trace = storage->garbage_collected_objects[i];
+
+    if (trace == NULL) {
+      continue;
+    }
+
+    if (check_sample_content(env, trace, frames, size, check_lines, PRINT_OUT)) {
+      event_storage_unlock(storage);
+      return TRUE;
+    }
+  }
+  event_storage_unlock(storage);
+  return FALSE;
+}
+
+// No mutex here, handled by the caller.
+static void event_storage_augment_storage(EventStorage* storage) {
+  int new_max = (storage->live_object_size * 2) + 1;
+  ObjectTrace** new_objects = reinterpret_cast<ObjectTrace**>(malloc(new_max * sizeof(*new_objects)));
+
+  int current_count = storage->live_object_count;
+  memcpy(new_objects, storage->live_objects, current_count * sizeof(*new_objects));
+  free(storage->live_objects);
+  storage->live_objects = new_objects;
+  storage->live_object_size = new_max;
+}
+
+static void event_storage_add(EventStorage* storage,
+                              JNIEnv* jni,
+                              jthread thread,
+                              jobject object,
+                              jclass klass,
+                              jlong size) {
+  jvmtiFrameInfo frames[64];
+  jint count;
+  jvmtiError err;
+
+  err = jvmti->GetStackTrace(thread, 0, 64, frames, &count);
+  if (err == JVMTI_ERROR_NONE && count >= 1) {
+    ObjectTrace* live_object;
+    jvmtiFrameInfo* allocated_frames = (jvmtiFrameInfo*) malloc(count * sizeof(*allocated_frames));
+    memcpy(allocated_frames, frames, count * sizeof(*allocated_frames));
+
+    live_object = (ObjectTrace*) malloc(sizeof(*live_object));
+    live_object->frames = allocated_frames;
+    live_object->frame_count = count;
+    live_object->size = size;
+    live_object->thread = thread;
+    live_object->object = jni->NewWeakGlobalRef(object);
+
+    if (jni->ExceptionOccurred()) {
+      jni->FatalError("Error in event_storage_add: Exception in jni NewWeakGlobalRef");
+    }
+
+    // Only now lock and get things done quickly.
+    event_storage_lock(storage);
+
+    storage->live_object_additions++;
+
+    if (storage->live_object_count >= storage->live_object_size) {
+      event_storage_augment_storage(storage);
+    }
+    assert(storage->live_object_count < storage->live_object_size);
+
+    if (PRINT_OUT) {
+      fprintf(stderr, "Adding trace for thread %p, frame_count %d, storage %p\n",
+              thread, count, storage);
+      print_out_frames(jni, live_object);
+    }
+    storage->live_objects[storage->live_object_count] = live_object;
+    storage->live_object_count++;
+
+    event_storage_unlock(storage);
+  }
+}
+
+static void event_storage_compact(EventStorage* storage, JNIEnv* jni) {
+  int max, i, dest;
+  ObjectTrace** live_objects;
+
+  event_storage_lock_compaction(storage);
+  storage->compaction_required = 0;
+  event_storage_unlock_compaction(storage);
+
+  event_storage_lock(storage);
+
+  max = storage->live_object_count;
+  live_objects = storage->live_objects;
+
+  for (i = 0, dest = 0; i < max; i++) {
+    ObjectTrace* live_object = live_objects[i];
+    jweak object = live_object->object;
+
+    if (!jni->IsSameObject(object, NULL)) {
+      if (dest != i) {
+        live_objects[dest] = live_object;
+        dest++;
+      }
+    } else {
+      jni->DeleteWeakGlobalRef(object);
+      live_object->object = NULL;
+
+      event_storage_add_garbage_collected_object(storage, live_object);
+    }
+  }
+
+  storage->live_object_count = dest;
+  event_storage_unlock(storage);
+}
+
+static void event_storage_free_objects(ObjectTrace** array, int max) {
+  int i;
+  for (i = 0; i < max; i++) {
+    free(array[i]), array[i] = NULL;
+  }
+}
+
+static void event_storage_reset(EventStorage* storage) {
+  event_storage_lock(storage);
+
+  // Reset everything except the mutex and the garbage collection.
+  event_storage_free_objects(storage->live_objects,
+                             storage->live_object_count);
+  storage->live_object_additions = 0;
+  storage->live_object_size = 0;
+  storage->live_object_count = 0;
+  free(storage->live_objects), storage->live_objects = NULL;
+
+  event_storage_free_objects(storage->garbage_collected_objects,
+                             storage->garbage_history_size);
+
+  storage->compaction_required = 0;
+  storage->garbage_history_index = 0;
+
+  event_storage_unlock(storage);
+}
+
+static int event_storage_number_additions(EventStorage* storage) {
+  int result;
+  event_storage_lock(storage);
+  result = storage->live_object_additions;
+  event_storage_unlock(storage);
+  return result;
+}
+
+// Start of the JVMTI agent code.
+static const char *EXC_CNAME = "java/lang/Exception";
+
+static int check_error(jvmtiError err, const char *s) {
+  if (err != JVMTI_ERROR_NONE) {
+    printf("  ## %s error: %d\n", s, err);
+    return 1;
+  }
+  return 0;
+}
+
+static int check_capability_error(jvmtiError err, const char *s) {
+  if (err != JVMTI_ERROR_NONE) {
+    if (err == JVMTI_ERROR_MUST_POSSESS_CAPABILITY) {
+      return 0;
+    }
+    fprintf(stderr, "  ## %s error: %d\n", s, err);
+  }
+  return 1;
+}
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+  return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+  return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+  return JNI_VERSION_1_8;
+}
+
+#define MAX_THREADS 500
+
+typedef struct ThreadStats {
+  int thread_count;
+  int counts[MAX_THREADS];
+  char* threads[MAX_THREADS];
+} ThreadStats;
+
+static ThreadStats thread_stats;
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitorThreadDisabledTest_checkThreadSamplesOnlyFrom(
+    JNIEnv* env, jclass cls, jthread thread) {
+  jvmtiThreadInfo info;
+  jvmtiError err;
+  char* expected_name;
+  int found_thread = FALSE;
+
+  err = jvmti->GetThreadInfo(thread, &info);
+  expected_name = info.name;
+
+  if (err != JVMTI_ERROR_NONE) {
+    fprintf(stderr, "Failed to get thread information\n");
+    return FALSE;
+  }
+
+  if (thread_stats.thread_count != 1) {
+    fprintf(stderr, "Wrong thread number: %d (expected 1)\n",
+            thread_stats.thread_count);
+    return FALSE;
+  }
+
+  if (strcmp(expected_name, thread_stats.threads[0]) != 0) {
+    fprintf(stderr, "Unexpected thread name: '%s' (expected '%s')\n",
+            thread_stats.threads[0], expected_name);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static void add_thread_count(jthread thread) {
+  int i;
+  jvmtiThreadInfo info;
+  jvmtiError err;
+
+  err = jvmti->GetThreadInfo(thread, &info);
+  if (err != JVMTI_ERROR_NONE) {
+    fprintf(stderr, "Thread info for %p failed, ignoring thread count\n",
+            thread);
+    return;
+  }
+
+  event_storage_lock(&global_event_storage);
+  for (i = 0; i < thread_stats.thread_count; i++) {
+    if (!strcmp(thread_stats.threads[i], info.name)) {
+      thread_stats.counts[i]++;
+      event_storage_unlock(&global_event_storage);
+      return;
+    }
+  }
+
+  thread_stats.threads[thread_stats.thread_count] = info.name;
+  thread_stats.counts[thread_stats.thread_count]++;
+  thread_stats.thread_count++;
+  event_storage_unlock(&global_event_storage);
+}
+
+JNIEXPORT void JNICALL
+Java_MyPackage_HeapMonitorThreadDisabledTest_enableSamplingEvents(
+    JNIEnv* env, jclass cls, jthread thread) {
+  fprintf(stderr, "Enabling for %p\n", thread);
+  check_error(jvmti->SetEventNotificationMode(
+      JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, thread),
+              "Set event notifications for a single thread");
+}
+
+static void print_thread_stats() {
+  int i;
+  event_storage_lock(&global_event_storage);
+  fprintf(stderr, "Thread count:\n");
+  for (i = 0; i < thread_stats.thread_count; i++) {
+    fprintf(stderr, "\t%s: %d\n", thread_stats.threads[i], thread_stats.counts[i]);
+  }
+  event_storage_unlock(&global_event_storage);
+}
+
+JNIEXPORT
+void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env,
+                                JNIEnv* jni_env,
+                                jthread thread,
+                                jobject object,
+                                jclass object_klass,
+                                jlong size) {
+  add_thread_count(thread);
+
+  if (event_storage_get_compaction_required(&global_event_storage)) {
+    event_storage_compact(&global_event_storage, jni_env);
+  }
+
+  event_storage_add(&global_event_storage, jni_env, thread, object,
+                    object_klass, size);
+}
+
+JNIEXPORT
+void JNICALL VMObjectAlloc(jvmtiEnv *jvmti_env,
+                           JNIEnv* jni_env,
+                           jthread thread,
+                           jobject object,
+                           jclass object_klass,
+                           jlong size) {
+  event_storage_add(&second_global_event_storage, jni_env, thread, object,
+                    object_klass, size);
+}
+
+JNIEXPORT
+void JNICALL GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
+  event_storage_set_compaction_required(&global_event_storage);
+}
+
+static int enable_notifications() {
+  if (check_error(jvmti->SetEventNotificationMode(
+      JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
+                     "Set event notifications")) {
+    return 1;
+  }
+
+  return check_error(jvmti->SetEventNotificationMode(
+      JVMTI_ENABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
+                     "Set event notifications");
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+  jint res;
+  jvmtiEventCallbacks callbacks;
+  jvmtiCapabilities caps;
+
+  res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION);
+  if (res != JNI_OK || jvmti == NULL) {
+    fprintf(stderr, "Error: wrong result of a valid call to GetEnv!\n");
+    return JNI_ERR;
+  }
+
+  // Get second jvmti environment.
+  res = jvm->GetEnv((void **) &second_jvmti, JVMTI_VERSION);
+  if (res != JNI_OK || second_jvmti == NULL) {
+    fprintf(stderr, "Error: wrong result of a valid second call to GetEnv!\n");
+    return JNI_ERR;
+  }
+
+  if (PRINT_OUT) {
+    fprintf(stderr, "Storage is at %p, secondary is at %p\n",
+            &global_event_storage, &second_global_event_storage);
+  }
+
+  jvmti->CreateRawMonitor("storage_monitor",
+                             &global_event_storage.storage_monitor);
+  jvmti->CreateRawMonitor("second_storage_monitor",
+                             &second_global_event_storage.storage_monitor);
+
+  jvmti->CreateRawMonitor("compaction_monitor",
+                             &global_event_storage.compaction_monitor);
+  jvmti->CreateRawMonitor("second_compaction_monitor",
+                             &second_global_event_storage.compaction_monitor);
+
+  event_storage_set_garbage_history(&global_event_storage, 200);
+  event_storage_set_garbage_history(&second_global_event_storage, 200);
+
+  memset(&callbacks, 0, sizeof(callbacks));
+  callbacks.SampledObjectAlloc = &SampledObjectAlloc;
+  callbacks.VMObjectAlloc = &VMObjectAlloc;
+  callbacks.GarbageCollectionFinish = &GarbageCollectionFinish;
+
+  memset(&caps, 0, sizeof(caps));
+  // Get line numbers, sample events, filename, and gc events for the tests.
+  caps.can_get_line_numbers = 1;
+  caps.can_get_source_file_name = 1;
+  caps.can_generate_garbage_collection_events = 1;
+  caps.can_generate_sampled_object_alloc_events = 1;
+  caps.can_generate_vm_object_alloc_events = 1;
+  if (check_error(jvmti->AddCapabilities(&caps), "Add capabilities")) {
+    return JNI_ERR;
+  }
+
+  if (check_error(jvmti->SetEventCallbacks(&callbacks,
+                                           sizeof(jvmtiEventCallbacks)),
+                  " Set Event Callbacks")) {
+    return JNI_ERR;
+  }
+  return JNI_OK;
+}
+
+JNIEXPORT void JNICALL
+Java_MyPackage_HeapMonitor_setSamplingInterval(JNIEnv* env, jclass cls, jint value) {
+  jvmti->SetHeapSamplingInterval(value);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitor_eventStorageIsEmpty(JNIEnv* env, jclass cls) {
+  return event_storage_get_count(&global_event_storage) == 0;
+}
+
+JNIEXPORT jint JNICALL
+Java_MyPackage_HeapMonitor_getEventStorageElementCount(JNIEnv* env, jclass cls) {
+  return event_storage_get_count(&global_event_storage);
+}
+
+JNIEXPORT void JNICALL
+Java_MyPackage_HeapMonitor_enableSamplingEvents(JNIEnv* env, jclass cls) {
+  enable_notifications();
+}
+
+JNIEXPORT void JNICALL
+Java_MyPackage_HeapMonitor_disableSamplingEvents(JNIEnv* env, jclass cls) {
+  check_error(jvmti->SetEventNotificationMode(
+      JVMTI_DISABLE, JVMTI_EVENT_SAMPLED_OBJECT_ALLOC, NULL),
+              "Set event notifications");
+
+  check_error(jvmti->SetEventNotificationMode(
+      JVMTI_DISABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL),
+              "Garbage Collection Finish");
+}
+
+static ExpectedContentFrame *get_native_frames(JNIEnv* env, jclass cls,
+                                               jobjectArray frames) {
+  ExpectedContentFrame *native_frames;
+  jsize size = env->GetArrayLength(frames);
+
+  if (env->ExceptionOccurred()) {
+    env->FatalError("get_native_frames failed with the GetArrayLength call");
+  }
+
+  native_frames = reinterpret_cast<ExpectedContentFrame*> (malloc(size * sizeof(*native_frames)));
+
+  if (native_frames == NULL) {
+    env->FatalError("Error in get_native_frames: malloc returned NULL\n");
+  }
+
+  if (fill_native_frames(env, frames, native_frames, size) != 0) {
+    env->FatalError("Error in get_native_frames: fill_native_frames returned failed status\n");
+  }
+
+  return native_frames;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitor_obtainedEvents(JNIEnv* env, jclass cls,
+                                          jobjectArray frames,
+                                          jboolean check_lines) {
+  jboolean result;
+  jsize size = env->GetArrayLength(frames);
+  ExpectedContentFrame *native_frames = get_native_frames(env, cls, frames);
+
+  result = event_storage_contains(env, &global_event_storage, native_frames,
+                                  size, check_lines);
+
+  free(native_frames), native_frames = NULL;
+  return result;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitor_garbageContains(JNIEnv* env, jclass cls,
+                                           jobjectArray frames,
+                                           jboolean check_lines) {
+  jboolean result;
+  jsize size = env->GetArrayLength(frames);
+  ExpectedContentFrame *native_frames = get_native_frames(env, cls, frames);
+
+  result = event_storage_garbage_contains(env, &global_event_storage,
+                                          native_frames, size, check_lines);
+
+  free(native_frames), native_frames = NULL;
+  return result;
+}
+
+JNIEXPORT jlong JNICALL
+Java_MyPackage_HeapMonitor_getSize(JNIEnv* env, jclass cls,
+                                   jobjectArray frames,
+                                   jboolean check_lines) {
+  jlong result = 0;
+  jsize size = env->GetArrayLength(frames);
+  ExpectedContentFrame *native_frames = get_native_frames(env, cls, frames);
+
+  result = event_storage_get_size(env, &global_event_storage,
+                                  native_frames, size, check_lines);
+
+  free(native_frames), native_frames = NULL;
+  return result;
+}
+
+JNIEXPORT void JNICALL
+Java_MyPackage_HeapMonitor_forceGarbageCollection(JNIEnv* env, jclass cls) {
+  check_error(jvmti->ForceGarbageCollection(),
+              "Forced Garbage Collection");
+}
+
+JNIEXPORT void JNICALL
+Java_MyPackage_HeapMonitor_resetEventStorage(JNIEnv* env, jclass cls) {
+  event_storage_reset(&global_event_storage);
+  event_storage_reset(&second_global_event_storage);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitorNoCapabilityTest_allSamplingMethodsFail(JNIEnv *env,
+                                                                  jclass cls) {
+  jvmtiCapabilities caps;
+  memset(&caps, 0, sizeof(caps));
+  caps.can_generate_sampled_object_alloc_events = 1;
+  if (check_error(jvmti->RelinquishCapabilities(&caps),
+                  "Add capabilities\n")){
+    return FALSE;
+  }
+
+  if (check_capability_error(jvmti->SetHeapSamplingInterval(1<<19),
+                             "Set Heap Sampling Interval")) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitorIllegalArgumentTest_testIllegalArgument(JNIEnv *env,
+                                                                  jclass cls) {
+  if (check_error(jvmti->SetHeapSamplingInterval(0),
+                  "Sampling interval 0 failed\n")){
+    return FALSE;
+  }
+
+  if (check_error(jvmti->SetHeapSamplingInterval(1024),
+                  "Sampling interval 1024 failed\n")){
+    return FALSE;
+  }
+
+  if (!check_error(jvmti->SetHeapSamplingInterval(-1),
+                   "Sampling interval -1 passed\n")){
+    return FALSE;
+  }
+
+  if (!check_error(jvmti->SetHeapSamplingInterval(-1024),
+                   "Sampling interval -1024 passed\n")){
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+JNIEXPORT jdouble JNICALL
+Java_MyPackage_HeapMonitor_getAverageSize(JNIEnv *env, jclass cls) {
+  return event_storage_get_average_size(&global_event_storage);
+}
+
+typedef struct sThreadsFound {
+  jthread* threads;
+  int num_threads;
+} ThreadsFound;
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitorThreadTest_checkSamples(JNIEnv* env, jclass cls,
+                                                  jint num_threads) {
+  print_thread_stats();
+  // Ensure we got stacks from at least num_threads.
+  return thread_stats.thread_count >= num_threads;
+}
+
+JNIEXPORT
+void JNICALL SampledObjectAlloc2(jvmtiEnv *jvmti_env,
+                                 JNIEnv* jni_env,
+                                 jthread thread,
+                                 jobject object,
+                                 jclass object_klass,
+                                 jlong size) {
+  // Nop for now, two agents are not yet implemented.
+  assert(0);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitorTwoAgentsTest_enablingSamplingInSecondaryAgent(
+    JNIEnv* env, jclass cls) {
+  // Currently this method should be failing directly at the AddCapability step
+  // but the implementation is correct for when multi-agent support is enabled.
+  jvmtiCapabilities caps;
+  jvmtiEventCallbacks callbacks;
+
+  memset(&caps, 0, sizeof(caps));
+  caps.can_generate_sampled_object_alloc_events = 1;
+  if (check_error(second_jvmti->AddCapabilities(&caps),
+                  "Set the capability for second agent")) {
+    return FALSE;
+  }
+
+  memset(&callbacks, 0, sizeof(callbacks));
+  callbacks.SampledObjectAlloc = &SampledObjectAlloc2;
+
+  if (check_error(second_jvmti->SetEventCallbacks(&callbacks,
+                                                  sizeof(jvmtiEventCallbacks)),
+                  " Set Event Callbacks for second agent")) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+JNIEXPORT void JNICALL
+Java_MyPackage_HeapMonitor_enableVMEvents(JNIEnv* env, jclass cls) {
+  check_error(jvmti->SetEventNotificationMode(
+      JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL),
+              "Set vm event notifications");
+}
+
+JNIEXPORT jint JNICALL
+Java_MyPackage_HeapMonitorVMEventsTest_vmEvents(JNIEnv* env, jclass cls) {
+  return event_storage_number_additions(&second_global_event_storage);
+}
+
+JNIEXPORT jint JNICALL
+Java_MyPackage_HeapMonitor_sampledEvents(JNIEnv* env, jclass cls) {
+  return event_storage_number_additions(&global_event_storage);
+}
+
+static jobject allocate_object(JNIEnv* env) {
+  // Construct an Object.
+  jclass cls = env->FindClass("java/lang/Object");
+  jmethodID constructor;
+  jobject result;
+
+  if (env->ExceptionOccurred() || cls == NULL) {
+    env->FatalError("Error in jni FindClass: Cannot find Object class\n");
+  }
+
+  constructor = env->GetMethodID(cls, "<init>", "()V");
+  if (env->ExceptionOccurred() || constructor == NULL) {
+    env->FatalError("Error in jni GetMethodID: Cannot find Object class constructor\n");
+  }
+
+  // Call back constructor to allocate a new instance, with an int argument
+  result = env->NewObject(cls, constructor);
+
+  if (env->ExceptionOccurred() || result == NULL) {
+    env->FatalError("Error in jni NewObject: Cannot allocate an object\n");
+  }
+  return result;
+}
+
+// Ensure we got a callback for the test.
+static int did_recursive_callback_test;
+
+JNIEXPORT
+void JNICALL RecursiveSampledObjectAlloc(jvmtiEnv *jvmti_env,
+                                         JNIEnv* jni_env,
+                                         jthread thread,
+                                         jobject object,
+                                         jclass object_klass,
+                                         jlong size) {
+  // Basically ensure that if we were to allocate objects, we would not have an
+  // infinite recursion here.
+  int i;
+  for (i = 0; i < 1000; i++) {
+    if (allocate_object(jni_env) == NULL) {
+      jni_env->FatalError("allocate_object returned NULL\n");
+    }
+  }
+
+  did_recursive_callback_test = 1;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_MyPackage_HeapMonitorRecursiveTest_didCallback(JNIEnv* env, jclass cls) {
+  return did_recursive_callback_test != 0;
+}
+
+JNIEXPORT void JNICALL
+Java_MyPackage_HeapMonitorRecursiveTest_setCallbackToCallAllocateSomeMore(JNIEnv* env, jclass cls) {
+  jvmtiEventCallbacks callbacks;
+
+  memset(&callbacks, 0, sizeof(callbacks));
+  callbacks.SampledObjectAlloc = &RecursiveSampledObjectAlloc;
+
+  if (check_error(jvmti->SetEventCallbacks(&callbacks,
+                                           sizeof(jvmtiEventCallbacks)),
+                  "Set Event Callbacks")) {
+    env->FatalError("Cannot reset the callback.");
+  }
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/Agent.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.security.*;
+import java.lang.instrument.*;
+import java.lang.reflect.*;
+
+public class Agent implements ClassFileTransformer {
+    public synchronized byte[] transform(final ClassLoader classLoader,
+                                         final String className,
+                                         Class<?> classBeingRedefined,
+                                         ProtectionDomain protectionDomain,
+                                         byte[] classfileBuffer) {
+        System.out.println("Transforming class " + className);
+        return classfileBuffer;
+    }
+
+    public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
+
+        try {
+            instrumentation.retransformClasses(to_redefine);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    public static void premain(String agentArgs, Instrumentation instrumentation) {
+        Agent transformer = new Agent();
+        instrumentation.addTransformer(transformer, true);
+
+        // Redefine java/lang/Object and java/lang/reflect/Method.invoke and
+        // java/lang/ClassLoader
+        Class object_class = Object.class;
+        redefine(agentArgs, instrumentation, object_class);
+
+        Class method_class = Method.class;
+        redefine(agentArgs, instrumentation, method_class);
+
+        Class loader_class = ClassLoader.class;
+        redefine(agentArgs, instrumentation, loader_class);
+
+        instrumentation.removeTransformer(transformer);
+    }
+
+    public static void main(String[] args) {
+        byte[] ba = new byte[0];
+
+        // If it survives 100 GC's, it's good.
+        for (int i = 0; i < 100 ; i++) {
+            System.gc();
+            ba.clone();
+        }
+        try {
+            // Use java/lang/reflect/Method.invoke to call
+            WalkThroughInvoke a = new WalkThroughInvoke();
+            Class aclass = WalkThroughInvoke.class;
+            Method m = aclass.getMethod("stackWalk");
+            m.invoke(a);
+        } catch (Exception x) {
+            x.printStackTrace();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ModifyAnonymous.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /test/lib
+ * @summary Test that retransforming and redefining anonymous classes gets UnmodifiableClassException
+ * @modules java.base/jdk.internal.misc
+ * @modules java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main ModifyAnonymous buildagent
+ * @run main/othervm -javaagent:redefineagent.jar ModifyAnonymous
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.lang.RuntimeException;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class ModifyAnonymous {
+
+    public static class LambdaTransformer implements ClassFileTransformer {
+        @Override
+        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
+                                ProtectionDomain protectionDomain, byte[] classfileBuffer)
+        throws IllegalClassFormatException {
+            return null;
+        }
+    }
+
+    static Instrumentation inst = null;
+    static volatile boolean done = false;
+
+    public static void premain(String args, Instrumentation instrumentation) {
+
+        inst = instrumentation;
+        System.out.println("javaagent in da house!");
+        instrumentation.addTransformer(new LambdaTransformer());
+    }
+
+    private static void buildAgent() {
+        try {
+            ClassFileInstaller.main("ModifyAnonymous");
+        } catch (Exception e) {
+            throw new RuntimeException("Could not write agent classfile", e);
+        }
+
+        try {
+            PrintWriter pw = new PrintWriter("MANIFEST.MF");
+            pw.println("Premain-Class: ModifyAnonymous");
+            pw.println("Agent-Class: ModifyAnonymous");
+            pw.println("Can-Retransform-Classes: true");
+            pw.println("Can-Redefine-Classes: true");
+            pw.close();
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException("Could not write manifest file for the agent", e);
+        }
+
+        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+        if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "ModifyAnonymous.class" })) {
+            throw new RuntimeException("Could not write the agent jar file");
+        }
+    }
+
+    public static class InstanceMethodCallSiteApp {
+
+        public static void test() throws InterruptedException {
+            for (int i = 0; i < 2; i++) {
+                InstanceMethodCallSiteApp app = new InstanceMethodCallSiteApp();
+                Runnable r = app::doWork;   // this creates an anonymous class
+                while (!done) {
+                    r.run();
+                    Thread.sleep(10);
+                }
+            }
+        }
+
+        public void doWork() {
+            System.out.print(".");
+        }
+    }
+
+    static void runTest() {
+        PrintWriter pw;
+        String logName = System.getProperty("test.classes") +
+            File.separator + "loadedClasses.log";
+        // Create a log file to capture the names of the classes in the
+        // allLoadedClasses array. The log file is for assisting in debugging
+        // in case a null class is encountered in the allLoadedClasses array.
+        try {
+            pw = new PrintWriter(new FileOutputStream(
+                new File(logName), true));
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException("Could not write loaded classes to log", e);
+        }
+        while (!done) {
+            Class[] allLoadedClasses = inst.getAllLoadedClasses();
+            int len = allLoadedClasses.length;
+            pw.println("    allLoadedClasses length: " + len);
+            for (int idx = 0; idx < len; idx++) {
+                Class cls = allLoadedClasses[idx];
+                pw.println("    " + idx + " " +
+                    ((cls != null) ? cls.getName() : "null"));
+            }
+            for (int idx = 0; idx < len; idx++) {
+                Class clazz = allLoadedClasses[idx];
+                if (clazz == null) {
+                    pw.flush();
+                    pw.close();
+                    throw new RuntimeException("null class encountered");
+                }
+                final String name = clazz.getName();
+                if (name.contains("$$Lambda$") && name.contains("App")) {
+                    if (inst.isModifiableClass(clazz)) {
+                        pw.flush();
+                        pw.close();
+                        throw new RuntimeException ("Class should not be modifiable");
+                    }
+                    // Try to modify them anyway.
+                    try {
+                        System.out.println("retransform called for " + name);
+                        inst.retransformClasses(clazz);
+                    } catch(java.lang.instrument.UnmodifiableClassException t) {
+                        System.out.println("PASSED: expecting UnmodifiableClassException");
+                        t.printStackTrace();
+                    }
+                    try {
+                        System.out.println("redefine called for " + name);
+                        String newclass = "class Dummy {}";
+                        byte[] bytecode = InMemoryJavaCompiler.compile("Dummy", newclass);
+                        ClassDefinition cld = new ClassDefinition(clazz, bytecode);
+                        inst.redefineClasses(new ClassDefinition[] { cld });
+                    } catch(java.lang.instrument.UnmodifiableClassException t) {
+                        System.out.println("PASSED: expecting UnmodifiableClassException");
+                        t.printStackTrace();
+                    } catch(java.lang.ClassNotFoundException e) {
+                        pw.flush();
+                        pw.close();
+                        throw new RuntimeException ("ClassNotFoundException thrown");
+                    }
+                    done = true;
+                }
+            }
+        }
+        pw.flush();
+        pw.close();
+    }
+
+    public static void main(String argv[]) throws InterruptedException, RuntimeException {
+        if (argv.length == 1 && argv[0].equals("buildagent")) {
+            buildAgent();
+            return;
+        }
+
+        if (inst == null) {
+            throw new RuntimeException("Instrumentation object was null");
+        }
+
+        new Thread() {
+            public void run() {
+                runTest();
+            }
+        }.start();
+
+        // Test that NCDFE is not thrown for anonymous class:
+        // ModifyAnonymous$InstanceMethodCallSiteApp$$Lambda$18
+        try {
+            ModifyAnonymous test = new ModifyAnonymous();
+            InstanceMethodCallSiteApp.test();
+        } catch (NoClassDefFoundError e) {
+            throw new RuntimeException("FAILED: NoClassDefFoundError thrown for " + e.getMessage());
+        }
+        System.out.println("PASSED: NoClassDefFound error not thrown");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAddLambdaExpression.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8193524
+ * @summary Redefine a class' public static method that contains a lambda expression
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineAddLambdaExpression
+ */
+
+interface MathOperation {
+    public int operation(int a, int b);
+}
+
+class B {
+    public static int operate(int a, int b, MathOperation mathOperation) {
+        return mathOperation.operation(a, b);
+    }
+    static int test_math(String p) {
+        MathOperation addition = (int a, int b) -> a + b;
+        return operate(10, 5, addition);
+    }
+}
+
+public class RedefineAddLambdaExpression {
+
+    public static String newB =
+        "class B {" +
+        "    public static int operate(int a, int b, MathOperation mathOperation) {" +
+        "        return mathOperation.operation(a, b);" +
+        "    }" +
+        "    static int test_math(String p) {" +
+        "        MathOperation addition = (int a, int b) -> a + b;" +
+        "        System.out.println(p + \" from class B's test_math method\");" +
+        "        MathOperation subtraction = (int a, int b) -> a - b;" +
+        "        return operate(10, 5, subtraction);" +
+        "    }" +
+        "}";
+
+    public static void main(String[] args) throws Exception {
+        int res = B.test_math("Hello");
+        System.out.println("Result = " + res);
+        if (res != 15) {
+            throw new Error("test_math returned " + res + " expected " + 15);
+        }
+        RedefineClassHelper.redefineClass(B.class, newB);
+
+        res = B.test_math("Hello");
+        if (res != 5)
+            throw new Error("test_math returned " + res + " expected " + 5);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /test/lib
+ * @summary Test that type annotations are retained after a retransform
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineAnnotations buildagent
+ * @run main/othervm -javaagent:redefineagent.jar RedefineAnnotations
+ */
+
+import static jdk.test.lib.Asserts.assertTrue;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.NoSuchFieldException;
+import java.lang.NoSuchMethodException;
+import java.lang.RuntimeException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.lang.reflect.AnnotatedArrayType;
+import java.lang.reflect.AnnotatedParameterizedType;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.AnnotatedWildcardType;
+import java.lang.reflect.Executable;
+import java.lang.reflect.TypeVariable;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.FieldVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.ASM7;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE_USE)
+@interface TestAnn {
+    String site();
+}
+
+public class RedefineAnnotations {
+    static Instrumentation inst;
+    public static void premain(String agentArgs, Instrumentation inst) {
+        RedefineAnnotations.inst = inst;
+    }
+
+    static class Transformer implements ClassFileTransformer {
+
+        public byte[] asm(ClassLoader loader, String className,
+                Class<?> classBeingRedefined,
+                ProtectionDomain protectionDomain, byte[] classfileBuffer)
+            throws IllegalClassFormatException {
+
+            ClassWriter cw = new ClassWriter(0);
+            ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { };
+            ClassReader cr = new ClassReader(classfileBuffer);
+            cr.accept(cv, 0);
+            return cw.toByteArray();
+        }
+
+        public class ReAddDummyFieldsClassVisitor extends ClassVisitor {
+
+            LinkedList<F> fields = new LinkedList<>();
+
+            public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) {
+                super(api, cv);
+            }
+
+            @Override public FieldVisitor visitField(int access, String name,
+                    String desc, String signature, Object value) {
+                if (name.startsWith("dummy")) {
+                    // Remove dummy field
+                    fields.addLast(new F(access, name, desc, signature, value));
+                    return null;
+                }
+                return cv.visitField(access, name, desc, signature, value);
+            }
+
+            @Override public void visitEnd() {
+                F f;
+                while ((f = fields.pollFirst()) != null) {
+                    // Re-add dummy fields
+                    cv.visitField(f.access, f.name, f.desc, f.signature, f.value);
+                }
+            }
+
+            private class F {
+                private int access;
+                private String name;
+                private String desc;
+                private String signature;
+                private Object value;
+                F(int access, String name, String desc, String signature, Object value) {
+                    this.access = access;
+                    this.name = name;
+                    this.desc = desc;
+                    this.signature = signature;
+                    this.value = value;
+                }
+            }
+        }
+
+        @Override public byte[] transform(ClassLoader loader, String className,
+                Class<?> classBeingRedefined,
+                ProtectionDomain protectionDomain, byte[] classfileBuffer)
+            throws IllegalClassFormatException {
+
+            if (className.contains("TypeAnnotatedTestClass")) {
+                try {
+                    // Here we remove and re-add the dummy fields. This shuffles the constant pool
+                    return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+                } catch (Throwable e) {
+                    // The retransform native code that called this method does not propagate
+                    // exceptions. Instead of getting an uninformative generic error, catch
+                    // problems here and print it, then exit.
+                    e.printStackTrace();
+                    System.exit(1);
+                }
+            }
+            return null;
+        }
+    }
+
+    private static void buildAgent() {
+        try {
+            ClassFileInstaller.main("RedefineAnnotations");
+        } catch (Exception e) {
+            throw new RuntimeException("Could not write agent classfile", e);
+        }
+
+        try {
+            PrintWriter pw = new PrintWriter("MANIFEST.MF");
+            pw.println("Premain-Class: RedefineAnnotations");
+            pw.println("Agent-Class: RedefineAnnotations");
+            pw.println("Can-Retransform-Classes: true");
+            pw.close();
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException("Could not write manifest file for the agent", e);
+        }
+
+        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+        if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineAnnotations.class" })) {
+            throw new RuntimeException("Could not write the agent jar file");
+        }
+    }
+
+    public static void main(String argv[]) throws NoSuchFieldException, NoSuchMethodException {
+        if (argv.length == 1 && argv[0].equals("buildagent")) {
+            buildAgent();
+            return;
+        }
+
+        if (inst == null) {
+            throw new RuntimeException("Instrumentation object was null");
+        }
+
+        RedefineAnnotations test = new RedefineAnnotations();
+        test.testTransformAndVerify();
+    }
+
+    // Class type annotations
+    private Annotation classTypeParameterTA;
+    private Annotation extendsTA;
+    private Annotation implementsTA;
+
+    // Field type annotations
+    private Annotation fieldTA;
+    private Annotation innerTA;
+    private Annotation[] arrayTA = new Annotation[4];
+    private Annotation[] mapTA = new Annotation[5];
+
+    // Method type annotations
+    private Annotation returnTA, methodTypeParameterTA, formalParameterTA, throwsTA;
+
+    private void testTransformAndVerify()
+        throws NoSuchFieldException, NoSuchMethodException {
+
+        Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
+        Class<?> myClass = c;
+
+        /*
+         * Verify that the expected annotations are where they should be before transform.
+         */
+        verifyClassTypeAnnotations(c);
+        verifyFieldTypeAnnotations(c);
+        verifyMethodTypeAnnotations(c);
+
+        try {
+            inst.addTransformer(new Transformer(), true);
+            inst.retransformClasses(myClass);
+        } catch (UnmodifiableClassException e) {
+            throw new RuntimeException(e);
+        }
+
+        /*
+         * Verify that the expected annotations are where they should be after transform.
+         * Also verify that before and after are equal.
+         */
+        verifyClassTypeAnnotations(c);
+        verifyFieldTypeAnnotations(c);
+        verifyMethodTypeAnnotations(c);
+    }
+
+    private void verifyClassTypeAnnotations(Class c) {
+        Annotation anno;
+
+        anno = c.getTypeParameters()[0].getAnnotations()[0];
+        verifyTestAnn(classTypeParameterTA, anno, "classTypeParameter");
+        classTypeParameterTA = anno;
+
+        anno = c.getAnnotatedSuperclass().getAnnotations()[0];
+        verifyTestAnn(extendsTA, anno, "extends");
+        extendsTA = anno;
+
+        anno = c.getAnnotatedInterfaces()[0].getAnnotations()[0];
+        verifyTestAnn(implementsTA, anno, "implements");
+        implementsTA = anno;
+    }
+
+    private void verifyFieldTypeAnnotations(Class c)
+        throws NoSuchFieldException, NoSuchMethodException {
+
+        verifyBasicFieldTypeAnnotations(c);
+        verifyInnerFieldTypeAnnotations(c);
+        verifyArrayFieldTypeAnnotations(c);
+        verifyMapFieldTypeAnnotations(c);
+    }
+
+    private void verifyBasicFieldTypeAnnotations(Class c)
+        throws NoSuchFieldException, NoSuchMethodException {
+
+        Annotation anno = c.getDeclaredField("typeAnnotatedBoolean").getAnnotatedType().getAnnotations()[0];
+        verifyTestAnn(fieldTA, anno, "field");
+        fieldTA = anno;
+    }
+
+    private void verifyInnerFieldTypeAnnotations(Class c)
+        throws NoSuchFieldException, NoSuchMethodException {
+
+        AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType();
+        Annotation anno = at.getAnnotations()[0];
+        verifyTestAnn(innerTA, anno, "inner");
+        innerTA = anno;
+    }
+
+    private void verifyArrayFieldTypeAnnotations(Class c)
+        throws NoSuchFieldException, NoSuchMethodException {
+
+        Annotation anno;
+        AnnotatedType at;
+
+        at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType();
+        anno = at.getAnnotations()[0];
+        verifyTestAnn(arrayTA[0], anno, "array1");
+        arrayTA[0] = anno;
+
+        for (int i = 1; i <= 3; i++) {
+            at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
+            anno = at.getAnnotations()[0];
+            verifyTestAnn(arrayTA[i], anno, "array" + (i + 1));
+            arrayTA[i] = anno;
+        }
+    }
+
+    private void verifyMapFieldTypeAnnotations(Class c)
+        throws NoSuchFieldException, NoSuchMethodException {
+
+        Annotation anno;
+        AnnotatedType atBase;
+        AnnotatedType atParameter;
+        atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType();
+
+        anno = atBase.getAnnotations()[0];
+        verifyTestAnn(mapTA[0], anno, "map1");
+        mapTA[0] = anno;
+
+        atParameter =
+            ((AnnotatedParameterizedType) atBase).
+            getAnnotatedActualTypeArguments()[0];
+        anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0];
+        verifyTestAnn(mapTA[1], anno, "map2");
+        mapTA[1] = anno;
+
+        anno =
+            ((AnnotatedWildcardType) atParameter).
+            getAnnotatedUpperBounds()[0].getAnnotations()[0];
+        verifyTestAnn(mapTA[2], anno, "map3");
+        mapTA[2] = anno;
+
+        atParameter =
+            ((AnnotatedParameterizedType) atBase).
+            getAnnotatedActualTypeArguments()[1];
+        anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0];
+        verifyTestAnn(mapTA[3], anno, "map4");
+        mapTA[3] = anno;
+
+        anno =
+            ((AnnotatedParameterizedType) atParameter).
+            getAnnotatedActualTypeArguments()[0].getAnnotations()[0];
+        verifyTestAnn(mapTA[4], anno, "map5");
+        mapTA[4] = anno;
+    }
+
+    private void verifyMethodTypeAnnotations(Class c)
+        throws NoSuchFieldException, NoSuchMethodException {
+        Annotation anno;
+        Executable typeAnnotatedMethod =
+            c.getDeclaredMethod("typeAnnotatedMethod", TypeAnnotatedTestClass.class);
+
+        anno = typeAnnotatedMethod.getAnnotatedReturnType().getAnnotations()[0];
+        verifyTestAnn(returnTA, anno, "return");
+        returnTA = anno;
+
+        anno = typeAnnotatedMethod.getTypeParameters()[0].getAnnotations()[0];
+        verifyTestAnn(methodTypeParameterTA, anno, "methodTypeParameter");
+        methodTypeParameterTA = anno;
+
+        anno = typeAnnotatedMethod.getAnnotatedParameterTypes()[0].getAnnotations()[0];
+        verifyTestAnn(formalParameterTA, anno, "formalParameter");
+        formalParameterTA = anno;
+
+        anno = typeAnnotatedMethod.getAnnotatedExceptionTypes()[0].getAnnotations()[0];
+        verifyTestAnn(throwsTA, anno, "throws");
+        throwsTA = anno;
+    }
+
+    private static void verifyTestAnn(Annotation verifyAgainst, Annotation anno, String expectedSite) {
+        verifyTestAnnSite(anno, expectedSite);
+
+        // When called before transform verifyAgainst will be null, when called
+        // after transform it will be the annotation from before the transform
+        if (verifyAgainst != null) {
+            assertTrue(anno.equals(verifyAgainst),
+                       "Annotations do not match before and after." +
+                       " Before: \"" + verifyAgainst + "\", After: \"" + anno + "\"");
+        }
+    }
+
+    private static void verifyTestAnnSite(Annotation testAnn, String expectedSite) {
+        String expectedAnn = "@TestAnn(site=\"" + expectedSite + "\")";
+        assertTrue(testAnn.toString().equals(expectedAnn),
+                   "Expected \"" + expectedAnn + "\", got \"" + testAnn + "\"");
+    }
+
+    public static class TypeAnnotatedTestClass <@TestAnn(site="classTypeParameter") S,T>
+            extends @TestAnn(site="extends") Thread
+            implements @TestAnn(site="implements") Runnable {
+
+        public @TestAnn(site="field") boolean typeAnnotatedBoolean;
+
+        public
+            RedefineAnnotations.
+            @TestAnn(site="inner") TypeAnnotatedTestClass
+            typeAnnotatedInner;
+
+        public
+            @TestAnn(site="array4") boolean
+            @TestAnn(site="array1") []
+            @TestAnn(site="array2") []
+            @TestAnn(site="array3") []
+            typeAnnotatedArray;
+
+        public @TestAnn(site="map1") Map
+            <@TestAnn(site="map2") ? extends @TestAnn(site="map3") String,
+            @TestAnn(site="map4")  List<@TestAnn(site="map5")  Object>> typeAnnotatedMap;
+
+        public int dummy1;
+        public int dummy2;
+        public int dummy3;
+
+        @TestAnn(site="return") <@TestAnn(site="methodTypeParameter") U,V> Class
+            typeAnnotatedMethod(@TestAnn(site="formalParameter") TypeAnnotatedTestClass arg)
+            throws @TestAnn(site="throws") ClassNotFoundException {
+
+            @TestAnn(site="local_variable_type") int foo = 0;
+            throw new ClassNotFoundException();
+        }
+
+        public void run() {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDeleteJmethod.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8181171
+ * @summary Test deleting static method pointing to by a jmethod
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/native/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineDeleteJmethod
+ */
+
+class B {
+    private static int deleteMe() { System.out.println("deleteMe called"); return 5; }
+    public static int callDeleteMe() { return deleteMe(); }
+}
+
+public class RedefineDeleteJmethod {
+
+    public static String newB =
+        "class B {" +
+            "public static int callDeleteMe() { return 6; }" +
+        "}";
+
+    public static String newerB =
+        "class B {" +
+            "private static int deleteMe() { System.out.println(\"deleteMe (2) called\"); return 7; }" +
+            "public static int callDeleteMe() { return deleteMe(); }" +
+        "}";
+
+
+    static {
+        System.loadLibrary("RedefineDeleteJmethod");
+    }
+
+    static native int jniCallDeleteMe();
+
+    static void test(int expected, boolean nsme_expected) throws Exception {
+        // Call through static method
+        int res = B.callDeleteMe();
+        System.out.println("Result = " + res);
+        if (res != expected) {
+            throw new Error("returned " + res + " expected " + expected);
+        }
+
+        // Call through jmethodID, saved from first call.
+        try {
+            res = jniCallDeleteMe();
+            if (nsme_expected) {
+                throw new RuntimeException("Failed, NoSuchMethodError expected");
+            }
+            if (res != expected) {
+                throw new Error("returned " + res + " expected " + expected);
+            }
+        } catch (NoSuchMethodError ex) {
+            if (!nsme_expected) {
+                throw new RuntimeException("Failed, NoSuchMethodError not expected");
+            }
+            System.out.println("Passed, NoSuchMethodError expected");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        test(5, false);
+        RedefineClassHelper.redefineClass(B.class, newB);
+        test(6, true);
+        RedefineClassHelper.redefineClass(B.class, newerB);
+        test(7, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDoubleDelete.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8178870 8010319
+ * @summary Redefine class with CFLH twice to test deleting the cached_class_file
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/native -Xlog:redefine+class+load+exceptions -agentlib:RedefineDoubleDelete -javaagent:redefineagent.jar RedefineDoubleDelete
+ */
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+// The ClassFileLoadHook for this class turns foo into faa and prints out faa.
+class RedefineDoubleDelete_B {
+    int faa() { System.out.println("foo"); return 1; }
+}
+
+public class RedefineDoubleDelete {
+
+    // Class gets a redefinition error because it adds a data member
+    public static String newB =
+                "class RedefineDoubleDelete_B {" +
+                "   int count1 = 0;" +
+                "}";
+
+    public static String newerB =
+                "class RedefineDoubleDelete_B { " +
+                "   int faa() { System.out.println(\"baa\"); return 2; }" +
+                "}";
+
+    public static void main(String args[]) throws Exception {
+
+        RedefineDoubleDelete_B b = new RedefineDoubleDelete_B();
+        int val = b.faa();
+        if (val != 1) {
+            throw new RuntimeException("return value wrong " + val);
+        }
+
+        // Redefine B twice to get cached_class_file in both B scratch classes
+        try {
+            RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
+        } catch (java.lang.UnsupportedOperationException e) {
+            // this is expected
+        }
+        try {
+            RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
+        } catch (java.lang.UnsupportedOperationException e) {
+            // this is expected
+        }
+
+        // Do a full GC.
+        System.gc();
+
+        // Redefine with a compatible class
+        RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newerB);
+        val = b.faa();
+        if (val != 2) {
+            throw new RuntimeException("return value wrong " + val);
+        }
+
+        // Do another full GC to clean things up.
+        System.gc();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineFinalizer.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6904403 8010319
+ * @summary Don't assert if we redefine finalize method
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
+ */
+
+/*
+ * Regression test for hitting:
+ *
+ * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
+ *
+ * when redefining finalizer method
+ */
+
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineFinalizer_B {
+    protected void finalize() {
+        // should be empty
+    }
+}
+
+public class RedefineFinalizer {
+
+    public static String newB =
+                "class RedefineFinalizer_B {" +
+                "   protected void finalize() { " +
+                "       System.out.println(\"Finalizer called\");" +
+                "   }" +
+                "}";
+
+    public static void main(String[] args) throws Exception {
+        RedefineClassHelper.redefineClass(RedefineFinalizer_B.class, newB);
+
+        A a = new A();
+    }
+
+    static class A extends RedefineFinalizer_B {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineInterfaceCall.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8174962 8010319
+ * @summary Redefine class with interface method call
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=trace RedefineInterfaceCall
+ */
+
+import static jdk.test.lib.Asserts.assertEquals;
+
+interface I1 { default int m() { return 0; } }
+interface I2 extends I1 {}
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineInterfaceCall_C implements I2 {
+    public int test(I2 i) {
+        return i.m(); // invokeinterface cpCacheEntry
+    }
+}
+
+public class RedefineInterfaceCall {
+
+    static String newI1 =
+      "interface I1 { default int m() { return 1; } }";
+
+    static String newC =
+        "class RedefineInterfaceCall_C implements I2 { " +
+        "  public int test(I2 i) { " +
+        "    return i.m(); " +
+        "  } " +
+        "} ";
+
+    static int test(I2 i) {
+        return i.m(); // invokeinterface cpCacheEntry
+    }
+
+    public static void main(String[] args) throws Exception {
+        RedefineInterfaceCall_C c = new RedefineInterfaceCall_C();
+
+        assertEquals(test(c),   0);
+        assertEquals(c.test(c), 0);
+
+        RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
+
+        assertEquals(c.test(c), 0);
+
+        RedefineClassHelper.redefineClass(I1.class, newI1);
+
+        assertEquals(test(c),   1);
+        assertEquals(c.test(c), 1);
+
+        RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
+
+        assertEquals(c.test(c), 1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineInterfaceMethods.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8081800 8010319
+ * @summary Redefine private and default interface methods
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineInterfaceMethods
+ */
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+interface RedefineInterfaceMethods_B {
+    int ORIGINAL_RETURN = 1;
+    int NEW_RETURN = 2;
+    private int privateMethod() {
+        return ORIGINAL_RETURN;
+    }
+    public default int defaultMethod() {
+        return privateMethod();
+    }
+}
+
+public class RedefineInterfaceMethods {
+
+    static final int RET = -2;
+
+    public static String redefinedPrivateMethod =
+        "interface RedefineInterfaceMethods_B {" +
+        "    int ORIGINAL_RETURN = 1;" +
+        "    int NEW_RETURN = 2;" +
+        "    private int privateMethod() {" +
+        "        return NEW_RETURN;" +
+        "    }" +
+        "    public default int defaultMethod() {" +
+        "       return privateMethod();" +
+        "    }" +
+        "}";
+
+    public static String redefinedDefaultMethod =
+        "interface RedefineInterfaceMethods_B {" +
+        "    int ORIGINAL_RETURN = 1;" +
+        "    int NEW_RETURN = 2;" +
+        "    private int privateMethod() {" +
+        "        return ORIGINAL_RETURN;" +
+        "    }" +
+        "    public default int defaultMethod() {" +
+        "       return RedefineInterfaceMethods.RET;" +
+        "    }" +
+        "}";
+
+    static class Impl implements RedefineInterfaceMethods_B {
+    }
+
+
+    public static void main(String[] args) throws Exception {
+
+        Impl impl = new Impl();
+
+        int res = impl.defaultMethod();
+        if (res != RedefineInterfaceMethods_B.ORIGINAL_RETURN)
+            throw new Error("defaultMethod returned " + res +
+                            " expected " + RedefineInterfaceMethods_B.ORIGINAL_RETURN);
+
+        RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedPrivateMethod);
+
+        res = impl.defaultMethod();
+        if (res != RedefineInterfaceMethods_B.NEW_RETURN)
+            throw new Error("defaultMethod returned " + res +
+                            " expected " + RedefineInterfaceMethods_B.NEW_RETURN);
+
+        System.gc();
+
+        RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedDefaultMethod);
+
+        res = impl.defaultMethod();
+        if (res != RET)
+            throw new Error("defaultMethod returned " + res +
+                            " expected " + RET);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineLeak.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @library /test/lib
+ * @summary Test that redefinition reuses metaspace blocks that are freed
+ * @modules java.base/jdk.internal.misc
+ * @modules java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineLeak buildagent
+ * @run main/othervm/timeout=6000  RedefineLeak runtest
+ */
+
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.RuntimeException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+import java.lang.instrument.IllegalClassFormatException;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class RedefineLeak {
+    static class Tester {}
+
+    static class LoggingTransformer implements ClassFileTransformer {
+        static int transformCount = 0;
+
+        public LoggingTransformer() {}
+
+        public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
+            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+
+            transformCount++;
+            if (transformCount % 1000 == 0) System.out.println("transformCount:" + transformCount);
+            return null;
+        }
+    }
+
+    public static void premain(String agentArgs, Instrumentation inst) throws Exception {
+        LoggingTransformer t = new LoggingTransformer();
+        inst.addTransformer(t, true);
+        {
+            Class demoClass = Class.forName("RedefineLeak$Tester");
+
+            for (int i = 0; i < 10000; i++) {
+               inst.retransformClasses(demoClass);
+            }
+        }
+        System.gc();
+    }
+    private static void buildAgent() {
+        try {
+            ClassFileInstaller.main("RedefineLeak");
+        } catch (Exception e) {
+            throw new RuntimeException("Could not write agent classfile", e);
+        }
+
+        try {
+            PrintWriter pw = new PrintWriter("MANIFEST.MF");
+            pw.println("Premain-Class: RedefineLeak");
+            pw.println("Agent-Class: RedefineLeak");
+            pw.println("Can-Redefine-Classes: true");
+            pw.println("Can-Retransform-Classes: true");
+            pw.close();
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException("Could not write manifest file for the agent", e);
+        }
+
+        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+        if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineLeak.class" })) {
+            throw new RuntimeException("Could not write the agent jar file");
+        }
+    }
+    public static void main(String argv[]) throws Exception {
+        if (argv.length == 1 && argv[0].equals("buildagent")) {
+            buildAgent();
+            return;
+        }
+        if (argv.length == 1 && argv[0].equals("runtest")) {
+            // run outside of jtreg to not OOM on jtreg classes that are loaded after metaspace is full
+            String[] javaArgs1 = { "-XX:MetaspaceSize=12m", "-XX:MaxMetaspaceSize=12m",
+                                   "-javaagent:redefineagent.jar", "RedefineLeak"};
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
+
+            OutputAnalyzer output = new OutputAnalyzer(pb.start());
+            output.shouldContain("transformCount:10000");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefinePreviousVersions.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8165246 8010319
+ * @summary Test has_previous_versions flag and processing during class unloading.
+ * @requires vm.opt.final.ClassUnloading
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm RedefinePreviousVersions test
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+// package access top-level classes to avoid problem with RedefineClassHelper
+// and nested types.
+
+class RedefinePreviousVersions_B { }
+
+class RedefinePreviousVersions_Running {
+    public static volatile boolean stop = false;
+    public static volatile boolean running = false;
+    static void localSleep() {
+        try {
+            Thread.sleep(10); // sleep for 10 ms
+        } catch(InterruptedException ie) {
+        }
+    }
+
+    public static void infinite() {
+        running = true;
+        while (!stop) { localSleep(); }
+    }
+}
+
+
+
+public class RedefinePreviousVersions {
+
+    public static String newB =
+                "class RedefinePreviousVersions_B {" +
+                "}";
+
+    public static String newRunning =
+        "class RedefinePreviousVersions_Running {" +
+        "    public static volatile boolean stop = true;" +
+        "    public static volatile boolean running = true;" +
+        "    static void localSleep() { }" +
+        "    public static void infinite() { }" +
+        "}";
+
+    public static void main(String[] args) throws Exception {
+
+        if (args.length > 0) {
+
+            // java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar",
+               "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
+               "RedefinePreviousVersions");
+            new OutputAnalyzer(pb.start())
+              .shouldContain("Class unloading: has_previous_versions = false")
+              .shouldContain("Class unloading: has_previous_versions = true")
+              .shouldHaveExitValue(0);
+            return;
+        }
+
+        // Redefine a class and create some garbage
+        // Since there are no methods running, the previous version is never added to the
+        // previous_version_list and the flag _has_previous_versions should stay false
+        RedefineClassHelper.redefineClass(RedefinePreviousVersions_B.class, newB);
+
+        for (int i = 0; i < 10 ; i++) {
+            String s = new String("some garbage");
+            System.gc();
+        }
+
+        // Start a class that has a method running
+        new Thread() {
+            public void run() {
+                RedefinePreviousVersions_Running.infinite();
+            }
+        }.start();
+
+        while (!RedefinePreviousVersions_Running.running) {
+            Thread.sleep(10); // sleep for 10 ms
+        }
+
+        // Since a method of newRunning is running, this class should be added to the previous_version_list
+        // of Running, and _has_previous_versions should return true at class unloading.
+        RedefineClassHelper.redefineClass(RedefinePreviousVersions_Running.class, newRunning);
+
+        for (int i = 0; i < 10 ; i++) {
+            String s = new String("some garbage");
+            System.gc();
+        }
+
+        // purge should clean everything up, except Xcomp it might not.
+        RedefinePreviousVersions_Running.stop = true;
+
+        for (int i = 0; i < 10 ; i++) {
+            String s = new String("some garbage");
+            System.gc();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8055008 8197901 8010319
+ * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace,class+loader+data=debug,safepoint+cleanup,gc+phases=debug:rt.log RedefineRunningMethods
+ */
+
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineRunningMethods_B {
+    static int count1 = 0;
+    static int count2 = 0;
+    public static volatile boolean stop = false;
+    static void localSleep() {
+        try{
+            Thread.currentThread().sleep(10);//sleep for 10 ms
+        } catch(InterruptedException ie) {
+        }
+    }
+
+    public static void infinite() {
+        while (!stop) { count1++; localSleep(); }
+    }
+    public static void infinite_emcp() {
+        while (!stop) { count2++; localSleep(); }
+    }
+}
+
+public class RedefineRunningMethods {
+
+    public static String newB =
+                "class RedefineRunningMethods_B {" +
+                "   static int count1 = 0;" +
+                "   static int count2 = 0;" +
+                "   public static volatile boolean stop = false;" +
+                "  static void localSleep() { " +
+                "    try{ " +
+                "      Thread.currentThread().sleep(10);" +
+                "    } catch(InterruptedException ie) { " +
+                "    } " +
+                " } " +
+                "   public static void infinite() { " +
+                "       System.out.println(\"infinite called\");" +
+                "   }" +
+                "   public static void infinite_emcp() { " +
+                "       while (!stop) { count2++; localSleep(); }" +
+                "   }" +
+                "}";
+
+    public static String evenNewerB =
+                "class RedefineRunningMethods_B {" +
+                "   static int count1 = 0;" +
+                "   static int count2 = 0;" +
+                "   public static volatile boolean stop = false;" +
+                "  static void localSleep() { " +
+                "    try{ " +
+                "      Thread.currentThread().sleep(1);" +
+                "    } catch(InterruptedException ie) { " +
+                "    } " +
+                " } " +
+                "   public static void infinite() { }" +
+                "   public static void infinite_emcp() { " +
+                "       System.out.println(\"infinite_emcp now obsolete called\");" +
+                "   }" +
+                "}";
+
+
+    public static void main(String[] args) throws Exception {
+
+        new Thread() {
+            public void run() {
+                RedefineRunningMethods_B.infinite();
+            }
+        }.start();
+
+        new Thread() {
+            public void run() {
+                RedefineRunningMethods_B.infinite_emcp();
+            }
+        }.start();
+
+        RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, newB);
+
+        System.gc();
+
+        RedefineRunningMethods_B.infinite();
+
+        // Start a thread with the second version of infinite_emcp running
+        new Thread() {
+            public void run() {
+                RedefineRunningMethods_B.infinite_emcp();
+            }
+        }.start();
+
+        for (int i = 0; i < 20 ; i++) {
+            String s = new String("some garbage");
+            System.gc();
+        }
+
+        RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, evenNewerB);
+        System.gc();
+
+        for (int i = 0; i < 20 ; i++) {
+            RedefineRunningMethods_B.infinite();
+            String s = new String("some garbage");
+            System.gc();
+        }
+
+        RedefineRunningMethods_B.infinite_emcp();
+
+        // purge should clean everything up.
+        RedefineRunningMethods_B.stop = true;
+
+        for (int i = 0; i < 20 ; i++) {
+            RedefineRunningMethods_B.infinite();
+            String s = new String("some garbage");
+            System.gc();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithBacktrace.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8087315 8010319
+ * @summary Get old method's stack trace elements after GC
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+class RedefineRunningMethodsWithBacktrace_B {
+    static int count1 = 0;
+    static int count2 = 0;
+    public static volatile boolean stop = false;
+    static void localSleep() {
+        try {
+            Thread.sleep(10);//sleep for 10 ms
+        } catch(InterruptedException ie) {
+        }
+    }
+
+    public static void infinite() {
+        while (!stop) { count1++; localSleep(); }
+    }
+    public static void throwable() {
+        // add some stuff to the original constant pool
+        String s1 = new String ("string1");
+        String s2 = new String ("string2");
+        String s3 = new String ("string3");
+        String s4 = new String ("string4");
+        String s5 = new String ("string5");
+        String s6 = new String ("string6");
+        String s7 = new String ("string7");
+        String s8 = new String ("string8");
+        String s9 = new String ("string9");
+        String s10 = new String ("string10");
+        String s11 = new String ("string11");
+        String s12 = new String ("string12");
+        String s13 = new String ("string13");
+        String s14 = new String ("string14");
+        String s15 = new String ("string15");
+        String s16 = new String ("string16");
+        String s17 = new String ("string17");
+        String s18 = new String ("string18");
+        String s19 = new String ("string19");
+        throw new RuntimeException("throwable called");
+    }
+}
+
+public class RedefineRunningMethodsWithBacktrace {
+
+    public static String newB =
+                "class RedefineRunningMethodsWithBacktrace_B {" +
+                "   static int count1 = 0;" +
+                "   static int count2 = 0;" +
+                "   public static volatile boolean stop = false;" +
+                "  static void localSleep() { " +
+                "    try{ " +
+                "      Thread.sleep(10);" +
+                "    } catch(InterruptedException ie) { " +
+                "    } " +
+                " } " +
+                "   public static void infinite() { " +
+                "       System.out.println(\"infinite called\");" +
+                "   }" +
+                "   public static void throwable() { " +
+                "       throw new RuntimeException(\"throwable called\");" +
+                "   }" +
+                "}";
+
+    public static String evenNewerB =
+                "class RedefineRunningMethodsWithBacktrace_B {" +
+                "   static int count1 = 0;" +
+                "   static int count2 = 0;" +
+                "   public static volatile boolean stop = false;" +
+                "  static void localSleep() { " +
+                "    try{ " +
+                "      Thread.sleep(1);" +
+                "    } catch(InterruptedException ie) { " +
+                "    } " +
+                " } " +
+                "   public static void infinite() { }" +
+                "   public static void throwable() { " +
+                "       throw new RuntimeException(\"throwable called\");" +
+                "   }" +
+                "}";
+
+    private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
+        System.out.println("touchRedefinedMethodInBacktrace: ");
+        throwable.printStackTrace();  // this actually crashes with the bug in
+                                      // java_lang_StackTraceElement::create()
+
+        // Make sure that we can convert the backtrace, which is referring to
+        // the redefined method, to a  StrackTraceElement[] without crashing.
+        StackTraceElement[] stackTrace = throwable.getStackTrace();
+        for (int i = 0; i < stackTrace.length; i++) {
+            StackTraceElement frame = stackTrace[i];
+            assertNotNull(frame.getClassName(),
+              "\nTest failed: trace[" + i + "].getClassName() returned null");
+            assertNotNull(frame.getMethodName(),
+              "\nTest failed: trace[" + i + "].getMethodName() returned null");
+        }
+    }
+
+    private static Throwable getThrowableInB() {
+        Throwable t = null;
+        try {
+            RedefineRunningMethodsWithBacktrace_B.throwable();
+        } catch (Exception e) {
+            t = e;
+            // Don't print here because Throwable will cache the constructed stacktrace
+            // e.printStackTrace();
+        }
+        return t;
+    }
+
+
+    public static void main(String[] args) throws Exception {
+
+        new Thread() {
+            public void run() {
+                RedefineRunningMethodsWithBacktrace_B.infinite();
+            }
+        }.start();
+
+        Throwable t1 = getThrowableInB();
+
+        RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, newB);
+
+        System.gc();
+
+        Throwable t2 = getThrowableInB();
+
+        RedefineRunningMethodsWithBacktrace_B.infinite();
+
+        for (int i = 0; i < 20 ; i++) {
+            String s = new String("some garbage");
+            System.gc();
+        }
+
+        RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, evenNewerB);
+        System.gc();
+
+        Throwable t3 = getThrowableInB();
+
+        for (int i = 0; i < 20 ; i++) {
+            RedefineRunningMethodsWithBacktrace_B.infinite();
+            String s = new String("some garbage");
+            System.gc();
+        }
+
+        touchRedefinedMethodInBacktrace(t1);
+        touchRedefinedMethodInBacktrace(t2);
+        touchRedefinedMethodInBacktrace(t3);
+
+        // purge should clean everything up.
+        RedefineRunningMethodsWithBacktrace_B.stop = true;
+
+        for (int i = 0; i < 20 ; i++) {
+            RedefineRunningMethodsWithBacktrace_B.infinite();
+            String s = new String("some garbage");
+            System.gc();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithResolutionErrors.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8076110
+ * @summary Redefine running methods that have cached resolution errors
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineRunningMethodsWithResolutionErrors
+ */
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
+
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        if (name.equals("C")) {
+            byte[] b = loadC(false);
+            return defineClass(name, b, 0, b.length);
+        } else {
+            return super.findClass(name);
+        }
+    }
+
+    private static byte[] loadC(boolean redefine) {
+        ClassWriter cw = new ClassWriter(0);
+
+        cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
+        {
+            MethodVisitor mv;
+
+            mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
+            mv.visitCode();
+
+            // First time we run we will:
+            // 1) Cache resolution errors
+            // 2) Redefine the class / method
+            // 3) Try to read the resolution errors that were cached
+            //
+            // The redefined method will never run, throw error to be sure
+            if (redefine) {
+                createThrowRuntimeExceptionCode(mv, "The redefined method was called");
+            } else {
+                createMethodBody(mv);
+            }
+            mv.visitMaxs(3, 0);
+            mv.visitEnd();
+        }
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+
+    private static void createMethodBody(MethodVisitor mv) {
+        Label classExists = new Label();
+
+        // Cache resolution errors
+        createLoadNonExistentClassCode(mv, classExists);
+
+        // Redefine our own class and method
+        mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
+
+        // Provoke the same error again to make sure the resolution error cache works
+        createLoadNonExistentClassCode(mv, classExists);
+
+        // Test passed
+        mv.visitInsn(RETURN);
+
+        mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
+        mv.visitLabel(classExists);
+
+        createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
+    }
+
+    private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
+        Label tryLoadBegin = new Label();
+        Label tryLoadEnd = new Label();
+        Label catchLoadBlock = new Label();
+        mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
+
+        // Try to load a class that does not exist to provoke resolution errors
+        mv.visitLabel(tryLoadBegin);
+        mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
+        mv.visitLabel(tryLoadEnd);
+
+        // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
+        mv.visitJumpInsn(GOTO, classExists);
+
+        mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
+        mv.visitLabel(catchLoadBlock);
+
+        // Ignore the expected NoClassDefFoundError
+        mv.visitInsn(POP);
+    }
+
+    private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
+        mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
+        mv.visitInsn(DUP);
+        mv.visitLdcInsn(msg);
+        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
+        mv.visitInsn(ATHROW);
+    }
+
+    private static Class<?> c;
+
+    public static void redefine() throws Exception {
+        RedefineClassHelper.redefineClass(c, loadC(true));
+    }
+
+    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
+        c.getMethod("m").invoke(null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSubtractLambdaExpression.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8193524
+ * @summary Redefine a class' public static method that contains a lambda expression
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineSubtractLambdaExpression
+ */
+
+interface MathOperation {
+    public int operation(int a, int b);
+}
+
+class B {
+    public static int operate(int a, int b, MathOperation mathOperation) {
+        return mathOperation.operation(a, b);
+    }
+    static int test_math(String p) {
+        System.out.println(p + " from class B's test_math method");
+        MathOperation subtraction = (int a, int b) -> a - b;
+        MathOperation addition = (int a, int b) -> a + b;
+        return operate(10, 5, addition);
+    }
+}
+
+public class RedefineSubtractLambdaExpression {
+
+    public static String newB =
+        "class B {" +
+        "    public static int operate(int a, int b, MathOperation mathOperation) {" +
+        "        return mathOperation.operation(a, b);" +
+        "    }" +
+        "    static int test_math(String p) {" +
+        "        MathOperation subtraction = (int a, int b) -> a - b;" +
+        "        return operate(10, 5, subtraction);" +
+        "    }" +
+        "}";
+
+    public static void main(String[] args) throws Exception {
+        int res = B.test_math("Hello");
+        System.out.println("Result = " + res);
+        if (res != 15) {
+            throw new Error("test_math returned " + res + " expected " + 15);
+        }
+        RedefineClassHelper.redefineClass(B.class, newB);
+
+        res = B.test_math("Hello");
+        if (res != 5)
+            throw new Error("test_math returned " + res + " expected " + 5);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RetransformClassesZeroLength.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8198393
+ * @summary Instrumentation.retransformClasses(new Class[0]) should be NOP
+ * @library /test/lib
+ * @modules java.instrument
+ * @compile RetransformClassesZeroLength.java
+ * @run main RetransformClassesZeroLength
+ */
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.ProtectionDomain;
+
+import jdk.test.lib.process.ProcessTools;
+
+
+public class RetransformClassesZeroLength {
+
+    private static String manifest =
+            "Premain-Class: " + RetransformClassesZeroLength.Agent.class.getName() + "\n"
+            + "Can-Retransform-Classes: true\n";
+
+    private static String CP = System.getProperty("test.classes");
+
+    public static void main(String args[]) throws Throwable {
+        String agentJar = buildAgent();
+        ProcessTools.executeProcess(
+                ProcessTools.createJavaProcessBuilder(
+                        "-javaagent:" + agentJar,
+                        "-version")
+        ).shouldHaveExitValue(0);
+    }
+
+    private static String buildAgent() throws Exception {
+        Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
+        String jarPath = jar.toAbsolutePath().toString();
+        ClassFileInstaller.writeJar(jarPath,
+                ClassFileInstaller.Manifest.fromString(manifest),
+                RetransformClassesZeroLength.class.getName());
+        return jarPath;
+    }
+
+
+    public static class Agent implements ClassFileTransformer {
+        public static void premain(String args, Instrumentation inst) {
+            inst.addTransformer(new NoOpTransformer());
+            try {
+                inst.retransformClasses(new Class[0]);
+            } catch (UnmodifiableClassException ex) {
+                throw new AssertionError(ex);
+            }
+        }
+    }
+
+    private static class NoOpTransformer implements ClassFileTransformer {
+        @Override
+        public byte[] transform(ClassLoader loader,
+                                String className,
+                                Class<?> classBeingRedefined,
+                                ProtectionDomain protectionDomain,
+                                byte[] classfileBuffer
+                                ) throws IllegalClassFormatException {
+            return null;    // no transform
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestLambdaFormRetransformation.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8008678
+ * @summary JSR 292: constant pool reconstitution must support pseudo strings
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.instrument
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @compile -XDignore.symbol.file TestLambdaFormRetransformation.java
+ * @run main TestLambdaFormRetransformation
+ */
+
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+
+import jdk.test.lib.process.ExitCode;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestLambdaFormRetransformation {
+    private static String MANIFEST = String.format("Manifest-Version: 1.0\n" +
+                                                   "Premain-Class: %s\n" +
+                                                   "Can-Retransform-Classes: true\n",
+                                                   Agent.class.getName());
+
+    private static String CP = System.getProperty("test.classes");
+
+    public static void main(String args[]) throws Throwable {
+        Path agent = TestLambdaFormRetransformation.buildAgent();
+        OutputAnalyzer oa = ProcessTools.executeTestJvm("-javaagent:" +
+                                agent.toAbsolutePath().toString(), "-version");
+        oa.shouldHaveExitValue(ExitCode.OK.value);
+    }
+
+    private static Path buildAgent() throws IOException {
+        Path manifest = TestLambdaFormRetransformation.createManifest();
+        Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
+
+        String[] args = new String[] {
+            "-cfm",
+            jar.toAbsolutePath().toString(),
+            manifest.toAbsolutePath().toString(),
+            "-C",
+            TestLambdaFormRetransformation.CP,
+            Agent.class.getName() + ".class"
+        };
+
+        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+
+        if (!jarTool.run(args)) {
+            throw new Error("jar failed: args=" + Arrays.toString(args));
+        }
+        return jar;
+    }
+
+    private static Path createManifest() throws IOException {
+        Path manifest = Files.createTempFile(Paths.get("."), null, ".mf");
+        byte[] manifestBytes = TestLambdaFormRetransformation.MANIFEST.getBytes();
+        Files.write(manifest, manifestBytes);
+        return manifest;
+    }
+}
+
+class Agent implements ClassFileTransformer {
+    private static Runnable lambda = () -> {
+        System.out.println("I'll crash you!");
+    };
+
+    public static void premain(String args, Instrumentation instrumentation) {
+        if (!instrumentation.isRetransformClassesSupported()) {
+            System.out.println("Class retransformation is not supported.");
+            return;
+        }
+        System.out.println("Calling lambda to ensure that lambda forms were created");
+
+        Agent.lambda.run();
+
+        System.out.println("Registering class file transformer");
+
+        instrumentation.addTransformer(new Agent());
+
+        for (Class c : instrumentation.getAllLoadedClasses()) {
+            if (c.getName().contains("LambdaForm") &&
+                instrumentation.isModifiableClass(c)) {
+                System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
+                try {
+                    instrumentation.retransformClasses(c);
+                } catch (UnmodifiableClassException e) {
+                    throw new AssertionError("Modification of modifiable class " +
+                                             "caused UnmodifiableClassException", e);
+                }
+            }
+        }
+    }
+
+    public static void main(String args[]) {
+    }
+
+    @Override
+    public byte[] transform(ClassLoader loader,
+                            String className,
+                            Class<?> classBeingRedefined,
+                            ProtectionDomain protectionDomain,
+                            byte[] classfileBuffer
+                           ) throws IllegalClassFormatException {
+        System.out.println("Transforming " + className);
+        return classfileBuffer.clone();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestMultipleClasses.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8139551
+ * @summary Scalability problem with redefinition - multiple code cache walks
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.instrument
+ *          jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -XX:CompileThreshold=100 -Xlog:redefine+class+nmethod=debug TestMultipleClasses
+ */
+
+import java.lang.instrument.*;
+import java.lang.reflect.*;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class TestMultipleClasses extends ClassLoader {
+
+    public static String B(int count) {
+        return new String("public class B" + count + " {" +
+                "   public static void compiledMethod() { " +
+                "       try{" +
+                "          Thread.sleep(1); " +
+                "       } catch(InterruptedException ie) {" +
+                "       }" +
+                "   }" +
+                "}");
+    }
+
+    static String newB(int count) {
+        return new String("public class B" + count + " {" +
+                "   public static void compiledMethod() { " +
+                "       System.out.println(\"compiledMethod called " + count + "\");" +
+                "   }" +
+                "}");
+    }
+
+    static int index = 0;
+
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        if (name.equals("B" + index)) {
+            byte[] b = InMemoryJavaCompiler.compile(name, B(index));
+            return defineClass(name, b, 0, b.length);
+        } else {
+            return super.findClass(name);
+        }
+    }
+
+    static void runCompiledMethodMethods(Class c, int count) throws Exception {
+        // Run for a while so they compile.
+        Object o = c.newInstance();
+        Method m = c.getMethod("compiledMethod");
+        for (int i = 0; i < count; i++) {
+            m.invoke(o);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        final int numberOfClasses = 20;
+        Class[] classes = new Class[numberOfClasses];
+        byte[][] newClass = new byte[numberOfClasses][];
+        ClassDefinition[] defs = new ClassDefinition[numberOfClasses];
+
+        TestMultipleClasses loader = new TestMultipleClasses();
+
+        // Load and start all the classes.
+        for (index = 0; index < numberOfClasses; index++) {
+            String name = new String("B" + index);
+            Class c = loader.findClass(name);
+
+            runCompiledMethodMethods(c, 500);
+            // Make class definition for redefinition
+            classes[index] = c;
+            newClass[index] = InMemoryJavaCompiler.compile(c.getName(), newB(index));
+            defs[index] = new ClassDefinition(c, newClass[index]);
+        }
+
+        long startTime = System.currentTimeMillis();
+
+        // Redefine all classes.
+        RedefineClassHelper.instrumentation.redefineClasses(defs);
+
+        long endTime = System.currentTimeMillis();
+
+        System.out.println("Redefinition took " + (endTime - startTime) + " milliseconds");
+
+        System.gc();
+
+        // Run all new classes.
+        for (index = 0; index < numberOfClasses; index++) {
+            runCompiledMethodMethods(classes[index], 1);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestRedefineObject.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.PrintWriter;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/*
+ * Test to redefine java/lang/Object and verify that it doesn't crash on vtable
+ * call on basic array type.
+ * Test to redefine java/lang/ClassLoader and java/lang/reflect/Method to make
+ * sure cached versions used afterward are the current version.
+ *
+ * @test
+ * @bug 8005056 8009728 8218399
+ * @requires !vm.graal.enabled
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.instrument
+ *          java.management
+ * @build Agent
+ * @run driver ClassFileInstaller Agent
+ * @run main TestRedefineObject
+ * @run main/othervm -javaagent:agent.jar -Xlog:redefine+class+load=debug,redefine+class+timer=info Agent
+ */
+public class TestRedefineObject {
+    public static void main(String[] args) throws Exception  {
+
+      PrintWriter pw = new PrintWriter("MANIFEST.MF");
+      pw.println("Premain-Class: Agent");
+      pw.println("Can-Retransform-Classes: true");
+      pw.close();
+
+      ProcessBuilder pb = new ProcessBuilder();
+      pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "Agent.class"});
+      pb.start().waitFor();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestRedefineWithUnresolvedClass.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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
+ * @summary Redefine a class with an UnresolvedClass reference in the constant pool.
+ * @bug 8035150
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.compiler
+ *          java.instrument
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ *          jdk.internal.jvmstat/sun.jvmstat.monitor
+ * @build UnresolvedClassAgent
+ * @run main TestRedefineWithUnresolvedClass
+ */
+
+import java.io.File;
+import java.util.Arrays;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestRedefineWithUnresolvedClass {
+
+    final static String slash = File.separator;
+    final static String testClasses = System.getProperty("test.classes") + slash;
+
+    public static void main(String... args) throws Throwable {
+        // delete this class to cause a NoClassDefFoundError
+        File unresolved = new File(testClasses, "MyUnresolvedClass.class");
+        if (unresolved.exists() && !unresolved.delete()) {
+            throw new Exception("Could not delete: " + unresolved);
+        }
+
+        // build the javaagent
+        buildJar("UnresolvedClassAgent");
+
+        // launch a VM with the javaagent
+        launchTest();
+    }
+
+    private static void buildJar(String jarName) throws Throwable {
+        String testSrc = System.getProperty("test.src", "?") + slash;
+
+        String jarPath = String.format("%s%s.jar", testClasses, jarName);
+        String manifestPath = String.format("%s%s.mf", testSrc, jarName);
+        String className = String.format("%s.class", jarName);
+
+        String[] args = new String[] {"-cfm", jarPath, manifestPath, "-C", testClasses, className};
+
+        System.out.println("Running jar " + Arrays.toString(args));
+        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+        if (!jarTool.run(args)) {
+            throw new Exception("jar failed: args=" + Arrays.toString(args));
+        }
+    }
+
+    private static void launchTest() throws Throwable {
+        String[] args = {
+            "-javaagent:" + testClasses + "UnresolvedClassAgent.jar",
+            "-Dtest.classes=" + testClasses,
+            "UnresolvedClassAgent" };
+        OutputAnalyzer output = ProcessTools.executeTestJvm(args);
+        output.shouldHaveExitValue(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/UnresolvedClassAgent.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.Instrumentation;
+
+/*
+ * This class is present during compilation, but will be deleted before execution.
+ */
+class MyUnresolvedClass {
+    static void bar() {
+    }
+}
+
+class MyRedefinedClass {
+    static void foo() {
+        MyUnresolvedClass.bar();
+    }
+}
+
+public class UnresolvedClassAgent {
+    public static void main(String... args) {
+    }
+
+    public static void premain(String args, Instrumentation inst) throws Exception {
+        try {
+            MyRedefinedClass.foo();
+        } catch(NoClassDefFoundError err) {
+            System.out.println("NoClassDefFoundError (expected)");
+        }
+
+        File f = new File(System.getProperty("test.classes"), "MyRedefinedClass.class");
+        byte[] buf = new byte[(int)f.length()];
+        try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
+            dis.readFully(buf);
+        }
+        ClassDefinition cd = new ClassDefinition(MyRedefinedClass.class, buf);
+        inst.redefineClasses(new ClassDefinition[] {cd});
+
+        try {
+            MyRedefinedClass.foo();
+        } catch(NoClassDefFoundError err) {
+            System.out.println("NoClassDefFoundError (expected again)");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/UnresolvedClassAgent.mf	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Premain-Class: UnresolvedClassAgent
+Can-Redefine-Classes: true
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/WalkThroughInvoke.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.lang.reflect.*;
+
+public class WalkThroughInvoke {
+  public void stackWalk() {
+      try {
+          Class b = Object.class;
+          SecurityManager sm = new SecurityManager();
+          // Walks the stack with Method.invoke in the stack (which is the
+          // purpose of the test) before it gets an AccessControlException.
+          sm.checkPermission(new RuntimePermission("accessDeclaredMembers"));
+      } catch (java.security.AccessControlException e) {
+          // Ignoring an 'AccessControlException' exception since
+          // it is expected as part of this test.
+      }
+  }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/libRedefineDeleteJmethod.c	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+
+jmethodID mid;
+jclass cls;
+static int count = 0;
+
+JNIEXPORT jint JNICALL
+Java_RedefineDeleteJmethod_jniCallDeleteMe(JNIEnv* env, jobject obj) {
+
+    if (count == 0) {
+      count++;
+      cls = (*env)->FindClass(env, "B");
+      if (NULL == cls) {
+          (*env)->FatalError(env, "could not find class");
+      }
+
+      mid = (*env)->GetStaticMethodID(env, cls, "deleteMe", "()I");
+      if (NULL == mid) {
+          (*env)->FatalError(env, "could not find method");
+      }
+    }
+
+    return (*env)->CallStaticIntMethod(env, cls, mid);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/libRedefineDoubleDelete.c	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+static jvmtiEnv *jvmti = NULL;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+    return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+    return JNI_VERSION_9;
+}
+
+
+static jint newClassDataLen = 0;
+static unsigned char* newClassData = NULL;
+
+static jint
+getBytecodes(jvmtiEnv *jvmti_env,
+             jint class_data_len, const unsigned char* class_data) {
+    int i;
+    jint res;
+
+    newClassDataLen = class_data_len;
+    res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
+    if (res != JNI_OK) {
+        printf("    Unable to allocate bytes\n");
+        return JNI_ERR;
+    }
+    for (i = 0; i < newClassDataLen; i++) {
+        newClassData[i] = class_data[i];
+        // Rewrite oo in class to aa
+        if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
+            newClassData[i] = newClassData[i-1] = 'a';
+        }
+    }
+    printf("  ... copied bytecode: %d bytes\n", (int)newClassDataLen);
+    return JNI_OK;
+}
+
+
+static void JNICALL
+Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
+                           jclass class_being_redefined,
+                           jobject loader, const char* name, jobject protection_domain,
+                           jint class_data_len, const unsigned char* class_data,
+                           jint *new_class_data_len, unsigned char** new_class_data) {
+    if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
+        if (newClassData == NULL) {
+            jint res = getBytecodes(jvmti_env, class_data_len, class_data);
+            if (res == JNI_ERR) {
+              printf(">>>    ClassFileLoadHook event: class name %s FAILED\n", name);
+              return;
+            }
+            // Only change for first CFLH event.
+            *new_class_data_len = newClassDataLen;
+            *new_class_data = newClassData;
+        }
+        printf(">>>    ClassFileLoadHook event: class name %s\n", name);
+    }
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+    jint res, size;
+    jvmtiCapabilities caps;
+    jvmtiEventCallbacks callbacks;
+    jvmtiError err;
+
+    res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+        JVMTI_VERSION_9);
+    if (res != JNI_OK || jvmti == NULL) {
+        printf("    Error: wrong result of a valid call to GetEnv!\n");
+        return JNI_ERR;
+    }
+
+    printf("Enabling following capabilities: can_generate_all_class_hook_events, "
+           "can_retransform_classes, can_redefine_classes");
+    memset(&caps, 0, sizeof(caps));
+    caps.can_generate_all_class_hook_events = 1;
+    caps.can_retransform_classes = 1;
+    caps.can_redefine_classes = 1;
+    printf("\n");
+
+    err = (*jvmti)->AddCapabilities(jvmti, &caps);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("    Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
+        return JNI_ERR;
+    }
+
+    size = (jint)sizeof(callbacks);
+
+    memset(&callbacks, 0, sizeof(callbacks));
+    callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
+
+    err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("    Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
+        return JNI_ERR;
+    }
+
+    err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
+    if (err != JVMTI_ERROR_NONE) {
+        printf("    Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
+        return JNI_ERR;
+    }
+
+    return JNI_OK;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- a/test/hotspot/jtreg/serviceability/jvmti/RetransformClassesZeroLength.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +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 8198393
- * @summary Instrumentation.retransformClasses(new Class[0]) should be NOP
- * @library /test/lib
- * @modules java.instrument
- * @compile RetransformClassesZeroLength.java
- * @run main RetransformClassesZeroLength
- */
-
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.ProtectionDomain;
-
-import jdk.test.lib.process.ProcessTools;
-
-
-public class RetransformClassesZeroLength {
-
-    private static String manifest =
-            "Premain-Class: " + RetransformClassesZeroLength.Agent.class.getName() + "\n"
-            + "Can-Retransform-Classes: true\n";
-
-    private static String CP = System.getProperty("test.classes");
-
-    public static void main(String args[]) throws Throwable {
-        String agentJar = buildAgent();
-        ProcessTools.executeProcess(
-                ProcessTools.createJavaProcessBuilder(
-                        "-javaagent:" + agentJar,
-                        "-version")
-        ).shouldHaveExitValue(0);
-    }
-
-    private static String buildAgent() throws Exception {
-        Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
-        String jarPath = jar.toAbsolutePath().toString();
-        ClassFileInstaller.writeJar(jarPath,
-                ClassFileInstaller.Manifest.fromString(manifest),
-                RetransformClassesZeroLength.class.getName());
-        return jarPath;
-    }
-
-
-    public static class Agent implements ClassFileTransformer {
-        public static void premain(String args, Instrumentation inst) {
-            inst.addTransformer(new NoOpTransformer());
-            try {
-                inst.retransformClasses(new Class[0]);
-            } catch (UnmodifiableClassException ex) {
-                throw new AssertionError(ex);
-            }
-        }
-    }
-
-    private static class NoOpTransformer implements ClassFileTransformer {
-        @Override
-        public byte[] transform(ClassLoader loader,
-                                String className,
-                                Class<?> classBeingRedefined,
-                                ProtectionDomain protectionDomain,
-                                byte[] classfileBuffer
-                                ) throws IllegalClassFormatException {
-            return null;    // no transform
-        }
-    }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/TestLambdaFormRetransformation.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2015, 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 8008678
- * @summary JSR 292: constant pool reconstitution must support pseudo strings
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- *          java.instrument
- *          java.management
- *          jdk.jartool/sun.tools.jar
- * @compile -XDignore.symbol.file TestLambdaFormRetransformation.java
- * @run main TestLambdaFormRetransformation
- */
-
-import java.io.IOException;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-
-import jdk.test.lib.process.ExitCode;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-public class TestLambdaFormRetransformation {
-    private static String MANIFEST = String.format("Manifest-Version: 1.0\n" +
-                                                   "Premain-Class: %s\n" +
-                                                   "Can-Retransform-Classes: true\n",
-                                                   Agent.class.getName());
-
-    private static String CP = System.getProperty("test.classes");
-
-    public static void main(String args[]) throws Throwable {
-        Path agent = TestLambdaFormRetransformation.buildAgent();
-        OutputAnalyzer oa = ProcessTools.executeTestJvm("-javaagent:" +
-                                agent.toAbsolutePath().toString(), "-version");
-        oa.shouldHaveExitValue(ExitCode.OK.value);
-    }
-
-    private static Path buildAgent() throws IOException {
-        Path manifest = TestLambdaFormRetransformation.createManifest();
-        Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
-
-        String[] args = new String[] {
-            "-cfm",
-            jar.toAbsolutePath().toString(),
-            manifest.toAbsolutePath().toString(),
-            "-C",
-            TestLambdaFormRetransformation.CP,
-            Agent.class.getName() + ".class"
-        };
-
-        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
-
-        if (!jarTool.run(args)) {
-            throw new Error("jar failed: args=" + Arrays.toString(args));
-        }
-        return jar;
-    }
-
-    private static Path createManifest() throws IOException {
-        Path manifest = Files.createTempFile(Paths.get("."), null, ".mf");
-        byte[] manifestBytes = TestLambdaFormRetransformation.MANIFEST.getBytes();
-        Files.write(manifest, manifestBytes);
-        return manifest;
-    }
-}
-
-class Agent implements ClassFileTransformer {
-    private static Runnable lambda = () -> {
-        System.out.println("I'll crash you!");
-    };
-
-    public static void premain(String args, Instrumentation instrumentation) {
-        if (!instrumentation.isRetransformClassesSupported()) {
-            System.out.println("Class retransformation is not supported.");
-            return;
-        }
-        System.out.println("Calling lambda to ensure that lambda forms were created");
-
-        Agent.lambda.run();
-
-        System.out.println("Registering class file transformer");
-
-        instrumentation.addTransformer(new Agent());
-
-        for (Class c : instrumentation.getAllLoadedClasses()) {
-            if (c.getName().contains("LambdaForm") &&
-                instrumentation.isModifiableClass(c)) {
-                System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
-                try {
-                    instrumentation.retransformClasses(c);
-                } catch (UnmodifiableClassException e) {
-                    throw new AssertionError("Modification of modifiable class " +
-                                             "caused UnmodifiableClassException", e);
-                }
-            }
-        }
-    }
-
-    public static void main(String args[]) {
-    }
-
-    @Override
-    public byte[] transform(ClassLoader loader,
-                            String className,
-                            Class<?> classBeingRedefined,
-                            ProtectionDomain protectionDomain,
-                            byte[] classfileBuffer
-                           ) throws IllegalClassFormatException {
-        System.out.println("Transforming " + className);
-        return classfileBuffer.clone();
-    }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/TestRedefineWithUnresolvedClass.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2014, 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.
- *
- * 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
- * @summary Redefine a class with an UnresolvedClass reference in the constant pool.
- * @bug 8035150
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- *          java.compiler
- *          java.instrument
- *          java.management
- *          jdk.jartool/sun.tools.jar
- *          jdk.internal.jvmstat/sun.jvmstat.monitor
- * @build UnresolvedClassAgent
- * @run main TestRedefineWithUnresolvedClass
- */
-
-import java.io.File;
-import java.util.Arrays;
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-public class TestRedefineWithUnresolvedClass {
-
-    final static String slash = File.separator;
-    final static String testClasses = System.getProperty("test.classes") + slash;
-
-    public static void main(String... args) throws Throwable {
-        // delete this class to cause a NoClassDefFoundError
-        File unresolved = new File(testClasses, "MyUnresolvedClass.class");
-        if (unresolved.exists() && !unresolved.delete()) {
-            throw new Exception("Could not delete: " + unresolved);
-        }
-
-        // build the javaagent
-        buildJar("UnresolvedClassAgent");
-
-        // launch a VM with the javaagent
-        launchTest();
-    }
-
-    private static void buildJar(String jarName) throws Throwable {
-        String testSrc = System.getProperty("test.src", "?") + slash;
-
-        String jarPath = String.format("%s%s.jar", testClasses, jarName);
-        String manifestPath = String.format("%s%s.mf", testSrc, jarName);
-        String className = String.format("%s.class", jarName);
-
-        String[] args = new String[] {"-cfm", jarPath, manifestPath, "-C", testClasses, className};
-
-        System.out.println("Running jar " + Arrays.toString(args));
-        sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
-        if (!jarTool.run(args)) {
-            throw new Exception("jar failed: args=" + Arrays.toString(args));
-        }
-    }
-
-    private static void launchTest() throws Throwable {
-        String[] args = {
-            "-javaagent:" + testClasses + "UnresolvedClassAgent.jar",
-            "-Dtest.classes=" + testClasses,
-            "UnresolvedClassAgent" };
-        OutputAnalyzer output = ProcessTools.executeTestJvm(args);
-        output.shouldHaveExitValue(0);
-    }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/UnresolvedClassAgent.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2014, 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.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.lang.instrument.ClassDefinition;
-import java.lang.instrument.Instrumentation;
-
-/*
- * This class is present during compilation, but will be deleted before execution.
- */
-class MyUnresolvedClass {
-    static void bar() {
-    }
-}
-
-class MyRedefinedClass {
-    static void foo() {
-        MyUnresolvedClass.bar();
-    }
-}
-
-public class UnresolvedClassAgent {
-    public static void main(String... args) {
-    }
-
-    public static void premain(String args, Instrumentation inst) throws Exception {
-        try {
-            MyRedefinedClass.foo();
-        } catch(NoClassDefFoundError err) {
-            System.out.println("NoClassDefFoundError (expected)");
-        }
-
-        File f = new File(System.getProperty("test.classes"), "MyRedefinedClass.class");
-        byte[] buf = new byte[(int)f.length()];
-        try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
-            dis.readFully(buf);
-        }
-        ClassDefinition cd = new ClassDefinition(MyRedefinedClass.class, buf);
-        inst.redefineClasses(new ClassDefinition[] {cd});
-
-        try {
-            MyRedefinedClass.foo();
-        } catch(NoClassDefFoundError err) {
-            System.out.println("NoClassDefFoundError (expected again)");
-        }
-    }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/UnresolvedClassAgent.mf	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Premain-Class: UnresolvedClassAgent
-Can-Redefine-Classes: true
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPrintStatics.java	Tue Mar 26 09:05:10 2019 -0400
@@ -60,8 +60,7 @@
                     "ClassLoaderDataGraph::_head",
                     "JNIHandles::_weak_global_handles", "PerfMemory::_top",
                     "ObjectSynchronizer::gBlockList",
-                    "java_lang_Class::_oop_size_offset",
-                    "CodeCache::_scavenge_root_nmethods"));
+                    "java_lang_Class::_oop_size_offset"));
             expStrMap.put("printstatics SystemDictionary", List.of(
                     "Static fields of SystemDictionary",
                     "SystemDictionary::Class_klass_knum",
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004/TestDescription.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove/remove004/TestDescription.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,6 +73,6 @@
  *      -waittime=5
  *      -debugee.vmkind=java
  *      -transport.address=dynamic
- *      "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}"
+ *      "-debugee.vmkeys=${test.vm.opts} ${test.java.opts} -Dtest.timeout.factor=${test.timeout.factor}"
  */
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004/TestDescription.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventQueue/remove_l/remove_l004/TestDescription.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -74,6 +74,6 @@
  *      -waittime=5
  *      -debugee.vmkind=java
  *      -transport.address=dynamic
- *      "-debugee.vmkeys=${test.vm.opts} ${test.java.opts}"
+ *      "-debugee.vmkeys=${test.vm.opts} ${test.java.opts} -Dtest.timeout.factor=${test.timeout.factor}"
  */
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Breakpoint/breakpoint001/breakpoint001.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/Breakpoint/breakpoint001/breakpoint001.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,7 @@
 static jvmtiEnv *jvmti = NULL;
 static jvmtiEventCallbacks callbacks;
 
-static int vm_started = 0;
+static volatile int callbacksEnabled = NSK_TRUE;
 static jrawMonitorID agent_lock;
 
 static void initCounters() {
@@ -82,7 +82,7 @@
 
     jvmti->RawMonitorEnter(agent_lock);
 
-    if (vm_started) {
+    if (callbacksEnabled) {
         // GetClassSignature may be called only during the start or the live phase
         if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &sig, &generic)))
             env->FatalError("failed to obtain a class signature\n");
@@ -196,11 +196,20 @@
 VMStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
     jvmti->RawMonitorEnter(agent_lock);
 
-    vm_started = 1;
+    callbacksEnabled = NSK_TRUE;
 
     jvmti->RawMonitorExit(agent_lock);
 }
 
+
+void JNICALL
+VMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
+    jvmti->RawMonitorEnter(agent_lock);
+
+    callbacksEnabled = NSK_FALSE;
+
+    jvmti->RawMonitorExit(agent_lock);
+}
 /************************/
 
 JNIEXPORT jint JNICALL
@@ -268,6 +277,8 @@
     callbacks.ClassLoad = &ClassLoad;
     callbacks.Breakpoint = &Breakpoint;
     callbacks.VMStart = &VMStart;
+    callbacks.VMDeath = &VMDeath;
+
     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks))))
         return JNI_ERR;
 
@@ -275,6 +286,8 @@
 
     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, NULL)))
         return JNI_ERR;
+    if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL)))
+        return JNI_ERR;
     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL)))
         return JNI_ERR;
     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL)))
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FramePop/framepop002/framepop002.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/FramePop/framepop002/framepop002.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,6 +62,9 @@
 static int max_depth = 0;
 static thr threads[MAX_THREADS];
 
+static volatile int callbacksEnabled = NSK_FALSE;
+static jrawMonitorID agent_lock;
+
 static
 int isTestThread(jvmtiEnv *jvmti_env, jthread thr) {
     jvmtiError err;
@@ -211,12 +214,20 @@
 
     if (watch_events == JNI_FALSE) return;
 
+    jvmti->RawMonitorEnter(agent_lock);
+
+    if (!callbacksEnabled) {
+        jvmti->RawMonitorExit(agent_lock);
+        return;
+    }
+
     err = jvmti_env->GetFrameCount(thr, &frameCount);
     if (err != JVMTI_ERROR_NONE) {
         printf("(GetFrameCount#entry) unexpected error: %s (%d)\n",
                TranslateError(err), err);
         printInfo(jvmti_env, thr, method, frameCount);
         result = STATUS_FAILED;
+        jvmti->RawMonitorExit(agent_lock);
         return;
     }
 
@@ -259,6 +270,25 @@
             }
         }
     }
+
+    jvmti->RawMonitorExit(agent_lock);
+}
+
+void JNICALL VMStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
+    jvmti->RawMonitorEnter(agent_lock);
+
+    callbacksEnabled = NSK_TRUE;
+
+    jvmti->RawMonitorExit(agent_lock);
+}
+
+
+void JNICALL VMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
+    jvmti->RawMonitorEnter(agent_lock);
+
+    callbacksEnabled = NSK_FALSE;
+
+    jvmti->RawMonitorExit(agent_lock);
 }
 
 void JNICALL FramePop(jvmtiEnv *jvmti_env, JNIEnv *env,
@@ -266,12 +296,19 @@
     jvmtiError err;
     jint frameCount;
 
+    jvmti->RawMonitorEnter(agent_lock);
+
+    if (!callbacksEnabled) {
+        jvmti->RawMonitorExit(agent_lock);
+        return;
+    }
     err = jvmti_env->GetFrameCount(thr, &frameCount);
     if (err != JVMTI_ERROR_NONE) {
         printf("(GetFrameCount#entry) unexpected error: %s (%d)\n",
                TranslateError(err), err);
         printInfo(jvmti_env, thr, method, frameCount);
         result = STATUS_FAILED;
+        jvmti->RawMonitorExit(agent_lock);
         return;
     }
 
@@ -296,6 +333,8 @@
             result = STATUS_FAILED;
         }
     }
+
+    jvmti->RawMonitorExit(agent_lock);
 }
 
 #ifdef STATIC_BUILD
@@ -355,12 +394,24 @@
             caps.can_generate_method_entry_events) {
         callbacks.MethodEntry = &MethodEntry;
         callbacks.FramePop = &FramePop;
+        callbacks.VMStart = &VMStart;
+        callbacks.VMDeath = &VMDeath;
+
         err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
         if (err != JVMTI_ERROR_NONE) {
             printf("(SetEventCallbacks) unexpected error: %s (%d)\n",
                    TranslateError(err), err);
             return JNI_ERR;
         }
+        if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, NULL)))
+            return JNI_ERR;
+        if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL)))
+            return JNI_ERR;
+
+        if (jvmti->CreateRawMonitor("agent_lock", &agent_lock) != JVMTI_ERROR_NONE) {
+            return JNI_ERR;
+        }
+
     } else {
         printf("Warning: FramePop or MethodEntry event is not implemented\n");
     }
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWait/monitorwait001/monitorwait001.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWait/monitorwait001/monitorwait001.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -147,10 +147,6 @@
             jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_MONITOR_WAIT, NULL)))
         nsk_jvmti_setFailStatus();
 
-    /* dispose global references */
-    jni->DeleteGlobalRef(object);
-    jni->DeleteGlobalRef(thread);
-
     return NSK_TRUE;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWaited/monitorwaited001/monitorwaited001.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/MonitorWaited/monitorwaited001/monitorwaited001.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -148,10 +148,6 @@
             jvmti->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_MONITOR_WAITED, NULL)))
         nsk_jvmti_setFailStatus();
 
-    /* dispose global references */
-    jni->DeleteGlobalRef(object);
-    jni->DeleteGlobalRef(thread);
-
     return NSK_TRUE;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002/TestDescription.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted002/TestDescription.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
  *
  * @library /vmTestbase
  *          /test/lib
+ * @requires !vm.graal.enabled
  * @run driver jdk.test.lib.FileInstaller . .
  * @run main/othervm/native
  *      -agentlib:resexhausted=-waittime=5
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
 import java.io.FileInputStream;
 import java.io.PrintStream;
 import java.security.ProtectionDomain;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
 
 import nsk.share.Consts;
 import nsk.share.test.Stresser;
@@ -77,12 +79,20 @@
 
 
     public static int run(String args[], PrintStream out) {
-        if ( args == null || args.length < 1 ) {
-            System.err.println("TEST BUG: Classes directory should be the first argument. Check .cfg file.");
+        String testclasspath = System.getProperty("test.class.path");
+        String [] testpaths = testclasspath.split(System.getProperty("path.separator"));
+        String classesDir = "";
+
+        Pattern pattern = Pattern.compile("^(.*)classes(.*)vmTestbase(.*)$");
+        for (int i = 0 ; i < testpaths.length; i++) {
+            if (pattern.matcher(testpaths[i]).matches()) {
+                classesDir = testpaths[i];
+            }
+        }
+        if (classesDir.equals("")) {
+            System.err.println("TEST BUG: Classes directory not found in test,class.path.");
             return Consts.TEST_FAILED;
         }
-
-        String classesDir = args[0];
         Stresser stress = new Stresser(args);
 
         String className = Helper.class.getName();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TEST.properties	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+exclusiveAccess.dirs=.
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted003/TestDescription.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,5 @@
  *      -XX:MaxMetaspaceSize=9m
  *      -XX:-UseGCOverheadLimit
  *      nsk.jvmti.ResourceExhausted.resexhausted003
- *      ../../classes/0/vmTestbase
  */
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/ResourceExhausted/resexhausted004/TestDescription.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,14 +39,12 @@
  * @library /vmTestbase
  *          /test/lib
  * @run driver jdk.test.lib.FileInstaller . .
- * @ignore 7013634 6606767
  * @run main/othervm/native
  *      -agentlib:resexhausted=-waittime=5
  *      -Xms16m
  *      -Xmx16m
- *      -XX:MaxMetaspaceSize=8m
+ *      -XX:MaxMetaspaceSize=9m
  *      -XX:-UseGCOverheadLimit
  *      nsk.jvmti.ResourceExhausted.resexhausted004
- *      ./bin/classes
  */
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SingleStep/singlestep003/singlestep003.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/SingleStep/singlestep003/singlestep003.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,9 @@
 static jvmtiEnv *jvmti = NULL;
 static jvmtiEventCallbacks callbacks;
 
+static volatile int callbacksEnabled = NSK_FALSE;
+static jrawMonitorID agent_lock;
+
 static void setBP(jvmtiEnv *jvmti_env, JNIEnv *env, jclass klass) {
     jmethodID mid;
 
@@ -76,6 +79,13 @@
 ClassLoad(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) {
     char *sig, *generic;
 
+    jvmti->RawMonitorEnter(agent_lock);
+
+    if (!callbacksEnabled) {
+        jvmti->RawMonitorExit(agent_lock);
+        return;
+    }
+
     if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(klass, &sig, &generic)))
         env->FatalError("failed to obtain a class signature\n");
 
@@ -86,6 +96,27 @@
             sig);
         setBP(jvmti_env, env, klass);
     }
+
+    jvmti->RawMonitorExit(agent_lock);
+}
+
+void JNICALL
+VMStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
+    jvmti->RawMonitorEnter(agent_lock);
+
+    callbacksEnabled = NSK_TRUE;
+
+    jvmti->RawMonitorExit(agent_lock);
+}
+
+
+void JNICALL
+VMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
+    jvmti->RawMonitorEnter(agent_lock);
+
+    callbacksEnabled = NSK_FALSE;
+
+    jvmti->RawMonitorExit(agent_lock);
 }
 
 void JNICALL
@@ -94,6 +125,13 @@
     jclass klass;
     char *sig, *generic;
 
+    jvmti->RawMonitorEnter(agent_lock);
+
+    if (!callbacksEnabled) {
+        jvmti->RawMonitorExit(agent_lock);
+        return;
+    }
+
     NSK_DISPLAY0("Breakpoint event received\n");
     if (!NSK_JVMTI_VERIFY(jvmti_env->GetMethodDeclaringClass(method, &klass)))
         NSK_COMPLAIN0("TEST FAILURE: unable to get method declaring class\n\n");
@@ -113,6 +151,8 @@
         NSK_COMPLAIN1("TEST FAILURE: unexpected breakpoint event in method of class \"%s\"\n\n",
             sig);
     }
+
+    jvmti->RawMonitorExit(agent_lock);
 }
 
 void JNICALL
@@ -276,16 +316,27 @@
     callbacks.ClassLoad = &ClassLoad;
     callbacks.Breakpoint = &Breakpoint;
     callbacks.SingleStep = &SingleStep;
+    callbacks.VMStart = &VMStart;
+    callbacks.VMDeath = &VMDeath;
+
     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks))))
         return JNI_ERR;
 
     NSK_DISPLAY0("setting event callbacks done\nenabling JVMTI events ...\n");
+    if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, NULL)))
+        return JNI_ERR;
+    if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL)))
+        return JNI_ERR;
     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL)))
         return JNI_ERR;
     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL)))
         return JNI_ERR;
     NSK_DISPLAY0("enabling the events done\n\n");
 
+    if (jvmti->CreateRawMonitor("agent_lock", &agent_lock) != JVMTI_ERROR_NONE) {
+        return JNI_ERR;
+    }
+
     return JNI_OK;
 }
 
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.cpp	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/jvmti_tools.cpp	Tue Mar 26 09:05:10 2019 -0400
@@ -584,6 +584,10 @@
 int isThreadExpected(jvmtiEnv *jvmti, jthread thread) {
     static const char *vm_jfr_buffer_thread_name = "VM JFR Buffer Thread";
     static const char *jfr_request_timer_thread_name = "JFR request timer";
+    static const char *graal_management_bean_registration_thread_name =
+                                            "HotSpotGraalManagement Bean Registration";
+    static const char *graal_compiler_thread_name_prefix = "JVMCI CompilerThread";
+    static const size_t prefixLength = strlen(graal_compiler_thread_name_prefix);
 
     jvmtiThreadInfo threadinfo;
     NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(thread, &threadinfo));
@@ -594,6 +598,13 @@
     if (strcmp(threadinfo.name, jfr_request_timer_thread_name) == 0)
         return 0;
 
+    if (strcmp(threadinfo.name, graal_management_bean_registration_thread_name) == 0)
+        return 0;
+
+    if ((strlen(threadinfo.name) > prefixLength) &&
+         strncmp(threadinfo.name, graal_compiler_thread_name_prefix, prefixLength) == 0)
+        return 0;
+
     return 1;
 }
 
--- a/test/jdk/ProblemList.txt	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/ProblemList.txt	Tue Mar 26 09:05:10 2019 -0400
@@ -114,7 +114,7 @@
 
 # jdk_awt
 
-java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.html 8168389 windows-all,macosx-all
+java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.java 8168389 windows-all,macosx-all
 java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java 8168408 windows-all,macosx-all
 java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generic-all
 java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all
@@ -127,7 +127,7 @@
 java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion.java 8060176 windows-all,macosx-all
 java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_1.java 8060176 windows-all,macosx-all
 java/awt/dnd/MissingEventsOnModalDialog/MissingEventsOnModalDialogTest.java 8164464 linux-all,macosx-all
-java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.html 8171510 macosx-all
+java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java 8171510 macosx-all
 javax/swing/dnd/7171812/bug7171812.java 8041447 macosx-all
 java/awt/Focus/ChoiceFocus/ChoiceFocus.java 8169103 windows-all,macosx-all
 java/awt/Focus/ClearLwQueueBreakTest/ClearLwQueueBreakTest.java 8198618 macosx-all
@@ -139,7 +139,7 @@
 java/awt/Focus/ShowFrameCheckForegroundTest/ShowFrameCheckForegroundTest.java 8028701 macosx-all,linux-all
 java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java 8159599 macosx-all
 java/awt/Focus/TypeAhead/TestFocusFreeze.java 8198622 macosx-all
-java/awt/Focus/ToFrontFocusTest/ToFrontFocus.html 7156130 linux-all
+java/awt/Focus/ToFrontFocusTest/ToFrontFocus.java 7156130 linux-all
 java/awt/Focus/WrongKeyTypedConsumedTest/WrongKeyTypedConsumedTest.java 8169096 macosx-all
 java/awt/event/KeyEvent/CorrectTime/CorrectTime.java 6626492 generic-all
 java/awt/EventQueue/6980209/bug6980209.java 8198615 macosx-all
@@ -149,7 +149,7 @@
 java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all
 java/awt/KeyboardFocusmanager/TypeAhead/EnqueueWithDialogButtonTest/EnqueueWithDialogButtonTest.java 8198623 macosx-all
 java/awt/KeyboardFocusmanager/TypeAhead/FreezeTest/FreezeTest.java 8198623 macosx-all
-java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.html 8198626 macosx-all
+java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.java 8198626 macosx-all
 java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java 8049405 macosx-all
 java/awt/Mixing/AWT_Mixing/OpaqueOverlappingChoice.java 8048171 generic-all
 java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java 8159451 linux-all,windows-all,macosx-all
@@ -166,7 +166,7 @@
 java/awt/Toolkit/RealSync/Test.java 6849383 macosx-all
 java/awt/LightweightComponent/LightweightEventTest/LightweightEventTest.java 8159252 windows-all
 java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java 8203047 macosx-all
-java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html 8073636 macosx-all
+java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java 8073636 macosx-all
 java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055 windows-all,linux-all
 java/awt/Focus/8013611/JDK8013611.java 8175366 windows-all,macosx-all
 java/awt/Focus/6378278/InputVerifierTest.java 8198616 macosx-all
@@ -182,7 +182,7 @@
 java/awt/event/KeyEvent/KeyMaskTest/KeyMaskTest.java 8129778 generic-all
 java/awt/event/MouseEvent/MouseButtonsAndKeyMasksTest/MouseButtonsAndKeyMasksTest.java 8129778 generic-all
 
-java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.html 8194947 generic-all
+java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java 8194947 generic-all
 java/awt/Frame/SetMaximizedBounds/SetMaximizedBounds.java 8196006 windows-all
 java/awt/Frame/FramesGC/FramesGC.java 8079069 macosx-all
 java/awt/FullScreen/AltTabCrashTest/AltTabCrashTest.java 8047218 generic-all
@@ -246,11 +246,11 @@
 java/awt/TextArea/TextAreaScrolling/TextAreaScrolling.java 8196300 windows-all
 java/awt/print/PrinterJob/PSQuestionMark.java 7003378 generic-all
 java/awt/print/PrinterJob/GlyphPositions.java 7003378 generic-all
-java/awt/Choice/PopupPosTest/PopupPosTest.html  8197811 windows-all
+java/awt/Choice/PopupPosTest/PopupPosTest.java  8197811 windows-all
 java/awt/Choice/ChoiceMouseWheelTest/ChoiceMouseWheelTest.java 7100044 macosx-all,linux-all
 java/awt/Component/CreateImage/CreateImage.java 8198334  windows-all
 java/awt/Component/GetScreenLocTest/GetScreenLocTest.java 4753654 generic-all
-java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.html 8017454 macosx-all
+java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java 8017454 macosx-all
 java/awt/Focus/NonFocusableWindowTest/NoEventsTest.java 8000171 windows-all
 java/awt/Frame/MiscUndecorated/RepaintTest.java 8079267 windows-all,linux-all
 java/awt/Robot/ModifierRobotKey/ModifierRobotKeyTest.java 8157173 generic-all
@@ -465,14 +465,14 @@
 java/awt/JAWT/JAWT.sh 8197798 windows-all,linux-all
 java/awt/Debug/DumpOnKey/DumpOnKey.java 8202667 windows-all
 java/awt/Robot/RobotWheelTest/RobotWheelTest.java 8129827 generic-all
-java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.html 8202926 linux-all
+java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java 8202926 linux-all
 java/awt/datatransfer/ConstructFlavoredObjectTest/ConstructFlavoredObjectTest.java 8202860 linux-all
 java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java 8202790 macosx-all,linux-all
-java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.html 8202882 linux-all
+java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java 8202882 linux-all
 java/awt/Frame/FramesGC/FramesGC.java 8079069 macosx-all
 java/awt/dnd/MissingDragExitEventTest/MissingDragExitEventTest.java 8030121 macosx-all,linux-all
 java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java 8202931 macosx-all,linux-all
-java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.html 7124275 macosx-all
+java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java 7124275 macosx-all
 java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java 6848810 macosx-all,linux-all
 java/awt/Component/NativeInLightShow/NativeInLightShow.java 8202932 linux-all
 java/awt/FileDialog/ModalFocus/FileDialogModalFocusTest.java 8194751 linux-all
@@ -481,7 +481,7 @@
 java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all
 java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all
 java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147 linux-all,solaris-all,windows-all
-java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.html 8148041 linux-all
+java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java 8148041 linux-all
 java/awt/Toolkit/DesktopProperties/rfe4758438.java 8193547 linux-all
 java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java 6847163
 java/awt/xembed/server/RunTestXEmbed.java 7034201 linux-all
@@ -683,6 +683,7 @@
 sun/security/pkcs11/tls/TestMasterSecret.java                   8204203 windows-all
 sun/security/pkcs11/tls/TestPRF.java                            8204203 windows-all
 sun/security/pkcs11/tls/TestPremaster.java                      8204203 windows-all
+sun/security/pkcs11/tls/tls12/TestTLS12.java                    8221271 windows-all
 sun/security/tools/keytool/NssTest.java                         8204203 windows-all
 
 ############################################################################
@@ -840,8 +841,6 @@
 
 # jdk_util
 
-java/util/Arrays/TimSortStackSize2.java                         8220005 generic-all
-
 ############################################################################
 
 # jdk_instrument
--- a/test/jdk/TEST.ROOT	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/TEST.ROOT	Tue Mar 26 09:05:10 2019 -0400
@@ -22,7 +22,12 @@
 javax/management sun/awt sun/java2d javax/xml/jaxp/testng/validation java/lang/ProcessHandle
 
 # Tests that cannot run concurrently
-exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi java/util/stream java/util/Arrays/largeMemory java/util/BitSet/stream javax/rmi
+exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote \
+sun/tools/jstatd sun/tools/jcmd sun/tools/jhsdb sun/tools/jhsdb/heapconfig \
+sun/tools/jinfo sun/tools/jmap sun/tools/jps sun/tools/jstack sun/tools/jstat \
+com/sun/tools/attach sun/security/mscapi java/util/stream java/util/Arrays/largeMemory \
+java/util/BitSet/stream javax/rmi
+
 # Group definitions
 groups=TEST.groups
 
@@ -42,6 +47,7 @@
     vm.compiler1.enabled \
     vm.compiler2.enabled \
     vm.cds \
+    vm.debug \
     vm.hasSA \
     vm.hasSAandCanAttach \
     vm.hasJFR \
--- a/test/jdk/TEST.groups	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/TEST.groups	Tue Mar 26 09:05:10 2019 -0400
@@ -103,8 +103,7 @@
     jdk/internal/ref \
     jdk/internal/jimage \
     jdk/internal/math \
-    jdk/modules \
-    vm
+    jdk/modules
 
 # All of the java.util package
 jdk_util = \
--- a/test/jdk/com/sun/jdi/SimulResumerTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/com/sun/jdi/SimulResumerTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -210,7 +210,9 @@
                 }
 
             } catch (IncompatibleThreadStateException ee) {
-                // ignore
+                // ignore checks if thread was not suspended
+            } catch (ObjectCollectedException ee) {
+                // ignore ownedMonitors failure
             } catch (VMDisconnectedException ee) {
                 // This is how we stop.  The debuggee runs to completion
                 // and we get this exception.
@@ -249,7 +251,7 @@
                 public void run() {
                     while (true) {
                         iters++;
-                        System.out.println("bkpts = " + bkpts + ", iters = " + iters);
+                        // System.out.println("bkpts = " + bkpts + ", iters = " + iters);
                         try {
                             Thread.sleep(waitTime);
                             check(debuggeeThread1);
--- a/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/com/sun/nio/sctp/SctpMultiChannel/SendFailed.java	Tue Mar 26 09:05:10 2019 -0400
@@ -28,6 +28,7 @@
 
 import com.sun.nio.sctp.*;
 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.nio.ByteBuffer;
--- a/test/jdk/java/awt/Choice/PopdownGeneratesMouseEvents/PopdownGeneratesMouseEvents.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- Copyright (c) 2011, 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.
--->
-<html>
-<!--
-  @test
-  @key headful
-  @bug 6200670
-  @summary MouseMoved events are triggered by Choice when mouse is moved outside the component, XToolkit
-  @library ../../regtesthelpers/
-  @author andrei.dmitriev area=choice
-  @build Util
-  @run applet PopdownGeneratesMouseEvents.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>PopdownGeneratesMouseEvents<br>Bug ID: 6200670 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="PopdownGeneratesMouseEvents.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Choice/PopdownGeneratesMouseEvents/PopdownGeneratesMouseEvents.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Choice/PopdownGeneratesMouseEvents/PopdownGeneratesMouseEvents.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -22,27 +22,32 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6200670
   @summary MouseMoved events are triggered by Choice when mouse is moved outside the component, XToolkit
   @library ../../regtesthelpers/
-  @author andrei.dmitriev area=choice
   @build Util
-  @run applet PopdownGeneratesMouseEvents.html
+  @run main PopdownGeneratesMouseEvents
 */
 
 import test.java.awt.regtesthelpers.Util;
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 
-public class PopdownGeneratesMouseEvents extends Applet {
+public class PopdownGeneratesMouseEvents extends Frame {
     private volatile Robot robot;
     private final Choice choice1 = new Choice();
 
     private volatile MouseMotionHandler mmh;
 
+    public static void main(final String[] args) {
+        PopdownGeneratesMouseEvents app = new PopdownGeneratesMouseEvents();
+        app.init();
+        app.start();
+    }
+
     public void init() {
         for (int i = 1; i < 10; i++) {
             choice1.add("item-0" + i);
@@ -61,6 +66,7 @@
 
     public void start() {
         setSize(300, 200);
+        setLocationRelativeTo(null);
         setVisible(true);
         validate();
         String toolkit = Toolkit.getDefaultToolkit().getClass().getName();
--- a/test/jdk/java/awt/Choice/PopupPosTest/PopupPosTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2004, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 5044150
-  @summary Tests that pupup doesn't popdown if no space to display under 
-  @author ssi@sparc.spb.su
-  @library /test/lib
-  @build jdk.test.lib.Platform
-  @run applet PopupPosTest.html
-  -->
-<head>
-<title> PopupPosTest </title>
-</head>
-<body>
-
-<h1>PopupPosTest<br>Bug ID: 5044150</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="PopupPosTest.class" WIDTH=350 HEIGHT=400></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Choice/PopupPosTest/PopupPosTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Choice/PopupPosTest/PopupPosTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,25 +22,23 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 5044150
   @summary Tests that pupup doesn't popdown if no space to display under
-  @author andrei.dmitriev area=awt.choice
   @library /test/lib
   @build jdk.test.lib.Platform
-  @run applet PopupPosTest.html
+  @run main PopupPosTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 
 import jdk.test.lib.Platform;
 
-public class PopupPosTest extends Applet
-{
-    public void start ()
-    {
+public class PopupPosTest {
+
+    public static void main(final String[] args) {
         if (Platform.isOSX()) {
             // On OS X, popup isn't under the mouse
             return;
--- a/test/jdk/java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +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.
--->
-
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug 6392086 8014725
-  @summary Tests basic DnD functionality in an applet
-  @author Alexey Utkin, Semyon Sadetsky area=dnd
-  @run applet HTMLTransferTest.html
--->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>HTMLTransferTest<br>Bug ID: 6392086</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="HTMLTransferTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Clipboard/HTMLTransferTest/HTMLTransferTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,26 +22,19 @@
  */
 
 /*
+  @test
+  @key headful
   @bug 6392086 8014725
-  @summary Tests basic DnD functionality in an applet
-  @author Alexey Utkin, Semyon Sadetsky
-  @run applet HTMLTransferTest.html
+  @summary tests that HTMLs of all supported native HTML formats are transfered
+           properly
+  @run main/othervm HTMLTransferTest
 */
 
-/**
- * HTMLTransferTest.java
- *
- * summary: tests that HTMLs of all supported native HTML formats
- *          are transfered properly
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.datatransfer.*;
 import java.io.*;
 
-
-public class HTMLTransferTest extends Applet {
+public class HTMLTransferTest {
     public static final int CODE_NOT_RETURNED = 100;
     public static final int CODE_CONSUMER_TEST_FAILED = 101;
     public static final int CODE_FAILURE = 102;
@@ -66,6 +59,12 @@
     private THTMLProducer imPr;
     private int returnCode = CODE_NOT_RETURNED;
 
+    public static void main(final String[] args) {
+        HTMLTransferTest app = new HTMLTransferTest();
+        app.init();
+        app.start();
+    }
+
     public void init() {
         initImpl();
 
--- a/test/jdk/java/awt/Component/F10TopToplevel/F10TopToplevel.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<!--
- Copyright (c) 2007, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6533175
-  @summary Block F10 if closest toplevel to keystroke target is not a Frame.
-  @author yuri nesterenko : area= awt.toplevel
-  @run applet F10TopToplevel.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>F10TopToplevel<br>Bug ID: 6533175 Pressing F10 when a modal dialog is visible hangs the Xserver, XToolkit</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="F10TopToplevel.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Component/F10TopToplevel/F10TopToplevel.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Component/F10TopToplevel/F10TopToplevel.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -20,51 +20,25 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 /*
-  test
+  @test
+  @key headful
   @bug 6533175
   @summary Block F10 if closest toplevel to keystroke target is not a Frame.
-  @author yuri nesterenko : area=awt.toplevel
-  @run applet F10TopToplevel.html
+  @run main F10TopToplevel
 */
 
-
-
-/**
- * F10TopToplevel.java
- *
- * summary: tests if F10 has no effect if focused toplevel if not Frame
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 
-
-public class F10TopToplevel extends Applet
-{
-    //Declare things used in the test, like buttons and labels here
-    Frame frame;
-    Dialog dialog;
-    volatile boolean menuToggled = false;
-
-    public void init()
-    {
-        setLayout (new BorderLayout ());
+public class F10TopToplevel {
 
-    }//End  init()
+    static Frame frame;
+    static Dialog dialog;
+    static volatile boolean menuToggled = false;
 
-    public void start ()
-    {
-        //Get things going.  Request focus, set size, et cetera
-        setSize (200,200);
-        setVisible(true);
-        validate();
-
-
-        //What would normally go into main() will probably go here.
-        //Use System.out.println for diagnostic messages that you want
-        //to read after the test is done.
+    public static void main(final String[] args) {
         MenuBar mb;
         Menu menu;
         MenuItem item;
@@ -115,6 +89,5 @@
             throw new RuntimeException("Oops! Menu should not open.");
         }
 
-    }// start()
-
+    }
 }// class F10TopToplevel
--- a/test/jdk/java/awt/ComponentOrientation/BorderTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/ComponentOrientation/BorderTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -39,9 +39,8 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 
-public class BorderTest extends Applet {
+public class BorderTest extends Panel {
     Panel       panel1;
     Panel       panel2;
 
@@ -108,8 +107,6 @@
         } );
 
         BorderTest BorderTest = new BorderTest();
-        BorderTest.init();
-        BorderTest.start();
 
         f.add("Center", BorderTest);
         f.setSize(450, 300);
--- a/test/jdk/java/awt/ComponentOrientation/FlowTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/ComponentOrientation/FlowTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -39,9 +39,8 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 
-public class FlowTest extends Applet {
+public class FlowTest extends Panel {
     Panel       panel;
 
     public FlowTest() {
@@ -141,8 +140,6 @@
         } );
 
         FlowTest flowTest = new FlowTest();
-        flowTest.init();
-        flowTest.start();
 
         f.add("Center", flowTest);
         f.setSize(300, 300);
--- a/test/jdk/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 1998, 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.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- or visit www.oracle.com if you need additional information or have any
- questions.
--->
-
-<HTML>
-  <!--  @test
-        @key headful
-        @bug 4023283
-        @summary Checks that an Error which propogate up to the EventDispatch
-        loop does not crash AWT.
-        @author Andrei Dmitriev: area=awt.event
-        @library ../../regtesthelpers
-        @modules java.desktop/sun.awt
-        @build Util
-        @run main LoopRobustness
-  -->
-  <HEAD>
-  <TITLE>LoopRobustness</TITLE>
-  </HEAD>
-  <BODY>
-  This is automatic test.
-  
-  <APPLET CODE="LoopRobustness.class"
-          CODEBASE = "."
-          WIDTH=350 HEIGHT=100>
-  </APPLET>
-  </BODY>                                                             
-  </HTML>
--- a/test/jdk/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,13 +22,14 @@
  */
 
 /**
- *
+ * @test
  * @bug 4023283
  * @key headful
  * @summary Checks that an Error which propogates up to the EventDispatch
  * loop does not crash AWT.
  * @author Andrei Dmitriev: area=awt.event
  * @library ../../regtesthelpers
+ * @modules java.desktop/sun.awt
  * @build Util
  * @run main LoopRobustness
  */
--- a/test/jdk/java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2006, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6448069
-  @summary namefilter is not called for file dialog on windows
-  @author oleg.sukhodolsky: area= awt.filedialog
-  @library ../../regtesthelpers
-  @build Util
-  @run applet FilenameFilterTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>FilenameFilterTest<br>Bug ID: 6448069 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="FilenameFilterTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2010, 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
@@ -22,20 +22,15 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6448069
   @summary namefilter is not called for file dialog on windows
-  @author oleg.sukhodolsky: area= awt.filedialog
-  @run applet FilenameFilterTest.html
+  @library ../../regtesthelpers
+  @build Util
+  @run main FilenameFilterTest
 */
 
-/**
- * FilenameFilterTest.java
- *
- * summary: namefilter is not called for file dialog on windows
- */
-
-import java.applet.Applet;
 import java.awt.*;
 
 import java.io.File;
@@ -43,28 +38,12 @@
 
 import test.java.awt.regtesthelpers.Util;
 
-public class FilenameFilterTest extends Applet
-{
-    //Declare things used in the test, like buttons and labels here
-    volatile boolean filter_was_called = false;
-    FileDialog fd;
-
-    public void init()
-    {
-        // Set up the environment -- set the layout manager, add
-        // buttons, etc.
+public class FilenameFilterTest {
 
-        setLayout (new BorderLayout ());
-
-    }//End  init()
+    static volatile boolean filter_was_called = false;
+    static FileDialog fd;
 
-    public void start ()
-    {
-        //Get things going.  Request focus, set size, et cetera
-        setSize (200,200);
-        setVisible(true);
-        validate();
-
+    public static void main(final String[] args) {
         EventQueue.invokeLater(new Runnable() {
                 public void run() {
                     fd = new FileDialog(new Frame(""), "hello world", FileDialog.LOAD);
@@ -93,6 +72,5 @@
         if (!filter_was_called) {
             throw new RuntimeException("Filter was not called");
         }
-    }// start()
-
+    }
 }// class FilenameFilterTest
--- a/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,7 +26,6 @@
   @key headful
   @bug       6314575
   @summary   Tests that previosly focused owned window doesn't steal focus when an owner's component requests focus.
-  @author    Anton.Tarasov: area=awt.focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main ActualFocusedWindowBlockingTest
@@ -34,12 +33,9 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class ActualFocusedWindowBlockingTest extends Applet {
+public class ActualFocusedWindowBlockingTest {
     Robot robot = Util.createRobot();
     Frame owner = new Frame("Owner Frame");
     Window win = new Window(owner);
--- a/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowRetaining.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowRetaining.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,7 +26,6 @@
   @key headful
   @bug      4823903
   @summary  Tests actual focused window retaining.
-  @author   Anton.Tarasov: area=awt.focus
   @library  ../../regtesthelpers
   @build    Util
   @run      main ActualFocusedWindowRetaining
@@ -34,11 +33,9 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.lang.reflect.*;
-import java.applet.*;
 import test.java.awt.regtesthelpers.Util;
 
-public class ActualFocusedWindowRetaining extends Applet {
+public class ActualFocusedWindowRetaining {
     public static Frame frame = new Frame("Other Frame");
     public static Frame owner = new Frame("Test Frame");
     public static Button otherButton1 = new Button("Other Button 1");
@@ -54,7 +51,6 @@
 
     public static void main(String[] args) {
         ActualFocusedWindowRetaining a = new ActualFocusedWindowRetaining();
-        a.init();
         a.start();
     }
 
@@ -76,10 +72,6 @@
                 }
             }, AWTEvent.WINDOW_EVENT_MASK | AWTEvent.WINDOW_FOCUS_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
 
-        setSize (500, 200);
-        setVisible(true);
-        validate();
-
         frame.setSize(new Dimension(400, 100));
         frame.setLocation(800, 400);
         frame.setVisible(true);
--- a/test/jdk/java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2008, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug 4041703 4096228 4025223 4260929
-  @summary Ensures that appletviewer sets a reasonable default focus for an Applet on start
-  @author  das area=appletviewer
-  @library ../../regtesthelpers
-  @build   Util
-  @run applet AppletInitialFocusTest.html
-  -->
-<head>
-<title> AppletInitialFocusTest </title>
-</head>
-<body>
-
-<h1>AppletInitialFocusTest<br>Bug ID: 4041703</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="AppletInitialFocusTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -22,30 +22,42 @@
  */
 
 /*
-  test
-  @bug     4041703 4096228 4025223 4260929
+  @test
+  @key headful
+  @bug 4041703 4096228 4025223 4260929
   @summary Ensures that appletviewer sets a reasonable default focus for an Applet on start
-  @author  das area=appletviewer
-  @run     applet AppletInitialFocusTest.html
+  @library ../../regtesthelpers
+  @build   Util
+  @run main AppletInitialFocusTest
 */
 
-import java.applet.Applet;
 import java.awt.Button;
-import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.Frame;
 import java.awt.Robot;
-import java.awt.Window;
 import test.java.awt.regtesthelpers.Util;
 
-public class AppletInitialFocusTest extends Applet {
+public class AppletInitialFocusTest extends Frame {
+
     Robot robot = Util.createRobot();
     Button button = new Button("Button");
 
-    public void init() {
-        add(button);
+    public static void main(final String[] args) throws Exception {
+        AppletInitialFocusTest app = new AppletInitialFocusTest();
+        app.init();
+        app.start();
     }
 
-    public void start() {
-        new Thread(new Runnable() {
+    public void init() {
+        setSize(200, 200);
+        setLocationRelativeTo(null);
+        setLayout(new FlowLayout());
+        add(button);
+        setVisible(true);
+    }
+
+    public void start() throws Exception {
+        Thread thread = new Thread(new Runnable() {
                 public void run() {
                     Util.waitTillShown(button);
                     robot.delay(1000); // delay the thread to let EDT to start dispatching focus events
@@ -54,6 +66,8 @@
                         throw new RuntimeException("Appletviewer doesn't set default focus correctly.");
                     }
                 }
-            }).start();
+            });
+        thread.start();
+        thread.join();
     }
 }
--- a/test/jdk/java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-<!--
- Copyright (c) 2008, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug 4411534 4517274
-  @summary ensures that user's requestFocus() during applet initialization
-           is not ignored
-  @author  prs area=appletviewer
-  @library ../../regtesthelpers
-  @build   Util
-  @run applet AppletInitialFocusTest1.html
-  -->
-<head>
-<title> AppletInitialFocusTest1 </title>
-</head>
-<body>
-
-<h1>AppletInitialFocusTest1<br>Bug ID: 4517274</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="AppletInitialFocusTest1.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -21,18 +21,36 @@
  * questions.
  */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 
-public class AppletInitialFocusTest1 extends Applet implements FocusListener {
+/*
+  @test
+  @key headful
+  @bug 4411534 4517274
+  @summary ensures that user's requestFocus() during applet initialization
+           is not ignored
+  @library ../../regtesthelpers
+  @build   Util
+  @run main AppletInitialFocusTest1
+ */
+public class AppletInitialFocusTest1 extends Frame implements FocusListener {
 
     Button button1 = new Button("Button1");
     Button button2 = new Button("Button2");
 
     Object lock = new Object();
 
+    public static void main(final String[] args) throws Exception {
+        AppletInitialFocusTest1 app = new AppletInitialFocusTest1();
+        app.init();
+        Thread.sleep(10000);
+    }
+
     public void init() {
+        setSize(200, 200);
+        setLocationRelativeTo(null);
+        setLayout(new FlowLayout());
 
         Component parent = this;
         while (parent != null && !(parent instanceof Window)) {
@@ -52,34 +70,18 @@
         button2.addFocusListener(this);
         add(button1);
         add(button2);
+        setVisible(true);
         button2.requestFocus();
     }
 
     public void focusGained(FocusEvent e) {
         if (e.getSource() == button1) {
             synchronized (lock) {
-                System.err.println("failed: focus on the wrong button");
-                System.exit(2);
+                throw new RuntimeException("failed: focus on the wrong button");
             }
         }
     }
 
     public void focusLost(FocusEvent e) {
     }
-
-    public void start() {
-        Thread thread = new Thread(new Runnable() {
-            public void run() {
-                try {
-                    Thread.sleep(10000);
-                    synchronized (lock) {
-                        System.err.println("passed");
-                        System.exit(0);
-                    }
-                } catch(InterruptedException e) {
-                }
-            }
-        });
-        thread.start();
-    }
 }
--- a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,20 +26,15 @@
   @key headful
   @bug       6187066
   @summary   Tests the Window.autoRequestFocus property for the Window.setVisible() method.
-  @author    anton.tarasov: area=awt.focus
   @library    ../../regtesthelpers
   @build      Util
   @run       main AutoRequestFocusSetVisibleTest
 */
 
 import java.awt.*;
-import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class AutoRequestFocusSetVisibleTest extends Applet {
+public class AutoRequestFocusSetVisibleTest {
     static Frame focusedFrame;
     static Button focusOwner;
     static Frame frame;
@@ -65,10 +60,6 @@
     }
 
     public void init() {
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
         toolkitClassName = Toolkit.getDefaultToolkit().getClass().getName();
     }
 
--- a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,7 +26,6 @@
   @key headful
   @bug       6187066
   @summary   Tests the Window.autoRequestFocus property for the Window.toFront() method.
-  @author    anton.tarasov: area=awt.focus
   @library /java/awt/patchlib     ../../regtesthelpers
   @build java.desktop/java.awt.Helper
   @build      Util
@@ -34,13 +33,9 @@
 */
 
 import java.awt.*;
-import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class AutoRequestFocusToFrontTest extends Applet {
+public class AutoRequestFocusToFrontTest {
     static boolean haveDelays;
 
     static Frame auxFrame;
@@ -76,10 +71,6 @@
     }
 
     public void init() {
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
         toolkitClassName = Toolkit.getDefaultToolkit().getClass().getName();
     }
 
--- a/test/jdk/java/awt/Focus/ChildWindowFocusTest/ChildWindowFocusTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2004, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug        5090325
-  @summary    Tests that Window's child can be focused on XAWT.
-  @author     anton.tarasov@sun.com: area=awt.focus
-  @run        applet ChildWindowFocusTest.html
-  -->
-<head>
-<title>ChildWindowFocusTest</title>
-</head>
-<body>
-
-<h1>ChildWindowFocusTest<br>Bug ID: 5090325</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="ChildWindowFocusTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/ChildWindowFocusTest/ChildWindowFocusTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ChildWindowFocusTest/ChildWindowFocusTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,19 +22,17 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug        5090325
   @summary    Tests that Window's child can be focused on XAWT.
-  @author     anton.tarasov@sun.com: area=awt.focus
-  @run        applet ChildWindowFocusTest.html
+  @run        main ChildWindowFocusTest
 */
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
-import java.lang.reflect.*;
 
-public class ChildWindowFocusTest extends Applet {
+public class ChildWindowFocusTest {
     Robot robot;
     Frame frame = new Frame("Owner");
     Button button0 = new Button("button-0");
@@ -46,16 +44,18 @@
     Button button1 = new Button("button-1");
     int shift;
 
+    public static void main(final String[] args) {
+        ChildWindowFocusTest app = new ChildWindowFocusTest();
+        app.init();
+        app.start();
+    }
+
     public void init() {
         try {
             robot = new Robot();
         } catch (AWTException e) {
             throw new RuntimeException("Error: unable to create robot", e);
         }
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
         shift = 100;
     }
 
--- a/test/jdk/java/awt/Focus/ClearLwQueueBreakTest/ClearLwQueueBreakTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ClearLwQueueBreakTest/ClearLwQueueBreakTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,7 +26,6 @@
   @key headful
   @bug       6496958
   @summary   Tests that breaking the proccess of clearing LW requests doesn't break focus.
-  @author    anton.tarasov@...: area=awt-focus
   @library    ../../regtesthelpers
   @build      Util
   @run       main ClearLwQueueBreakTest
@@ -35,11 +34,10 @@
 import java.awt.*;
 import javax.swing.*;
 import java.awt.event.*;
-import java.applet.Applet;
 import test.java.awt.regtesthelpers.Util;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-public class ClearLwQueueBreakTest extends Applet {
+public class ClearLwQueueBreakTest {
     JFrame f1 = new JFrame("frame");
     JFrame f2 = new JFrame("frame");
     JButton b = new JButton("button");
@@ -60,11 +58,6 @@
 
     public void init() {
         robot = Util.createRobot();
-
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
@@ -118,6 +111,7 @@
         f1.add(tf3);
         f1.setLayout(new FlowLayout());
         f1.pack();
+        f1.setLocationRelativeTo(null);
         f1.setVisible(true);
         Util.waitForIdle(robot);
 
--- a/test/jdk/java/awt/Focus/CloseDialogActivateOwnerTest/CloseDialogActivateOwnerTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/CloseDialogActivateOwnerTest/CloseDialogActivateOwnerTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,20 +26,15 @@
   @key headful
   @bug       6785058
   @summary   Tests that an owner is activated on closing its owned dialog with the warning icon.
-  @author    Anton Tarasov: area=awt.focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main/othervm/policy=java.policy -Djava.security.manager CloseDialogActivateOwnerTest
 */
 
 import java.awt.*;
-import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class CloseDialogActivateOwnerTest extends Applet {
+public class CloseDialogActivateOwnerTest {
     Robot robot;
 
     public static void main(String[] args) {
--- a/test/jdk/java/awt/Focus/ConsumeNextKeyTypedOnModalShowTest/ConsumeNextKeyTypedOnModalShowTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ConsumeNextKeyTypedOnModalShowTest/ConsumeNextKeyTypedOnModalShowTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -22,11 +22,10 @@
  */
 
 /*
-  @test      %W% %E%
+  @test
   @key headful
   @bug       6637607
   @summary   Showing a modal dlg on TAB KEY_PRESS shouldn't consume inappropriate KEY_TYPED.
-  @author    Anton Tarasov: area=awt-focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main ConsumeNextKeyTypedOnModalShowTest
@@ -34,12 +33,9 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class ConsumeNextKeyTypedOnModalShowTest extends Applet {
+public class ConsumeNextKeyTypedOnModalShowTest {
     Robot robot;
     Frame frame = new Frame("Frame");
     Dialog dialog = new Dialog(frame, "Dialog", true);
@@ -76,6 +72,7 @@
     }
 
     public void start() {
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
         Util.waitTillShown(frame);
 
--- a/test/jdk/java/awt/Focus/ContainerFocusAutoTransferTest/ContainerFocusAutoTransferTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ContainerFocusAutoTransferTest/ContainerFocusAutoTransferTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,13 +26,11 @@
   @key headful
   @bug       6607170
   @summary   Tests for focus-auto-transfer.
-  @author    Anton Tarasov: area=awt-focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main ContainerFocusAutoTransferTest
 */
 
-import java.applet.Applet;
 import java.awt.AWTEvent;
 import java.awt.Component;
 import java.awt.ComponentOrientation;
@@ -50,7 +48,7 @@
 import javax.swing.JPanel;
 import test.java.awt.regtesthelpers.Util;
 
-public class ContainerFocusAutoTransferTest extends Applet {
+public class ContainerFocusAutoTransferTest {
     Robot robot;
     TestFrame frame;
     KeyboardFocusManager kfm;
--- a/test/jdk/java/awt/Focus/DeiconifiedFrameLoosesFocus/DeiconifiedFrameLoosesFocus.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- Copyright (c) 2006, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6480534
-  @summary    A Frame changing its state from ICONIFIED to NORMAL should regain focus.
-  @author     anton.tarasov@...: area=awt.focus
-  @library    ../../regtesthelpers
-  @build      Util
-  @run        applet DeiconifiedFrameLoosesFocus.html
-  -->
-<head>
-<title>DeiconifiedFrameLoosesFocus</title>
-</head>
-<body>
- 
-<h1>DeiconifiedFrameLoosesFocus<br>Bug ID: 6480534</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=DeiconifiedFrameLoosesFocus.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/DeiconifiedFrameLoosesFocus/DeiconifiedFrameLoosesFocus.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/DeiconifiedFrameLoosesFocus/DeiconifiedFrameLoosesFocus.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2007, 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
@@ -22,18 +22,19 @@
  */
 
 /*
-  test
-  @bug       6480534
-  @summary   A Frame changing its state from ICONIFIED to NORMAL should regain focus.
-  @author    anton.tarasov@...: area=awt.focus
-  @run       applet DeiconifiedFrameLoosesFocus.html
+  @test
+  @key headful
+  @bug        6480534
+  @summary    A Frame changing its state from ICONIFIED to NORMAL should regain focus.
+  @library    ../../regtesthelpers
+  @build      Util
+  @run        main DeiconifiedFrameLoosesFocus
 */
 
 import java.awt.*;
-import java.applet.Applet;
 import test.java.awt.regtesthelpers.Util;
 
-public class DeiconifiedFrameLoosesFocus extends Applet {
+public class DeiconifiedFrameLoosesFocus {
     Robot robot;
     static final Frame frame = new Frame("Frame");
 
@@ -45,11 +46,6 @@
 
     public void init() {
         robot = Util.createRobot();
-
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
--- a/test/jdk/java/awt/Focus/FocusEmbeddedFrameTest/FocusEmbeddedFrameTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/FocusEmbeddedFrameTest/FocusEmbeddedFrameTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -26,7 +26,6 @@
  * @key       headful
  * @bug       6516675
  * @summary   Tests that EmbeddedFrame can be focused.
- * @author    anton.tarasov: area=awt-focus
  * @requires (os.family == "windows")
  * @modules   java.desktop/java.awt.peer
  *            java.desktop/sun.awt
@@ -39,13 +38,10 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 import test.java.awt.regtesthelpers.UtilInternal;
 
-public class FocusEmbeddedFrameTest extends Applet {
+public class FocusEmbeddedFrameTest {
     static Frame embedder = new Frame("Embedder");
     static Frame ef = null;
     static volatile boolean passed;
--- a/test/jdk/java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -22,11 +22,10 @@
  */
 
 /*
-  @test      FocusOwnerFrameOnClick.java %W% %E%
+  @test
   @key headful
   @bug       6886678
   @summary   Tests that clicking an owner frame switches focus from its owned window.
-  @author    Anton Tarasov: area=awt.focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main FocusOwnerFrameOnClick
@@ -34,12 +33,10 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class FocusOwnerFrameOnClick extends Applet {
+public class FocusOwnerFrameOnClick {
     Robot robot;
     Frame frame = new Frame("Frame");
     Window window = new Window(frame);
--- a/test/jdk/java/awt/Focus/FocusSubRequestTest/FocusSubRequestTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2004, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug        5082319
-  @summary    Tests that focus request for already focused component doesn't block key events.
-  @author     anton.tarasov@sun.com
-  @run applet FocusSubRequestTest.html
-  -->
-<head>
-<title>FocusSubRequestTest</title>
-</head>
-<body>
-
-<h1>FocusSubRequestTest<br>Bug ID: 5082319</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="FocusSubRequestTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/FocusSubRequestTest/FocusSubRequestTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/FocusSubRequestTest/FocusSubRequestTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -22,23 +22,28 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug        5082319
   @summary    Tests that focus request for already focused component doesn't block key events.
-  @author     anton.tarasov@sun.com
-  @run applet FocusSubRequestTest.html
+  @run main FocusSubRequestTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 
-public class FocusSubRequestTest extends Applet {
+public class FocusSubRequestTest {
     Frame frame = new Frame("Test Frame");
     Button button = new Button("button");
     boolean passed = false;
     Robot robot;
 
+    public static void main(final String[] args) {
+        FocusSubRequestTest app = new FocusSubRequestTest();
+        app.init();
+        app.start();
+    }
+
     public void init() {
         frame.add(button);
         button.addFocusListener(new FocusAdapter() {
@@ -64,7 +69,7 @@
 
     public void start() {
         frame.pack();
-        frame.setLocation(getLocation().x + getSize().width + 20, 0);
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
 
         waitTillShown(button);
--- a/test/jdk/java/awt/Focus/FrameJumpingToMouse/FrameJumpingToMouse.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/FrameJumpingToMouse/FrameJumpingToMouse.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,26 +26,19 @@
  * @key headful
  * @bug        4752312
  * @summary    Tests that after moving non-focusable window it ungrabs mouse pointer
- * @author     Denis Mikhalkin: area=awt.focus
  * @library    ../../regtesthelpers
  * @build      Util
  * @run        main FrameJumpingToMouse
  */
 
-import java.applet.Applet;
-import java.awt.BorderLayout;
-import java.awt.Dialog;
-import java.awt.Frame;
 import java.awt.Point;
 import java.awt.Robot;
-import java.awt.TextArea;
-import java.awt.Toolkit;
 import java.awt.event.InputEvent;
 import javax.swing.JFrame;
 import test.java.awt.regtesthelpers.Util;
 
-public class FrameJumpingToMouse extends Applet
-{
+public class FrameJumpingToMouse {
+
     JFrame frame = new JFrame("Test jumping frame");
     Robot robot = Util.createRobot();
 
--- a/test/jdk/java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,18 +26,16 @@
   @key headful
   @bug       6522725
   @summary   Tests for proper request-focus-back on FOCUS_LOST.
-  @author    Anton Tarasov: area=awt-focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main IconifiedFrameFocusChangeTest
 */
 
 import java.awt.*;
-import java.applet.Applet;
 import java.awt.event.*;
 import test.java.awt.regtesthelpers.Util;
 
-public class IconifiedFrameFocusChangeTest extends Applet {
+public class IconifiedFrameFocusChangeTest {
     Frame testFrame = new Frame("Test Frame");
     Frame otherFrame = new Frame("Other Frame");
     Button testButton = new Button("test button");
--- a/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- Copyright (c) 2006, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6426132
-  @summary    Modal blocked window shouldn't steal focus when shown, or brought to front.
-  @author     anton.tarasov@...: area=awt.focus
-  @library    ../../regtesthelpers        
-  @build      Util   
-  @run        applet ModalBlockedStealsFocusTest.html
-  -->
-<head>
-<title>ModalBlockedStealsFocusTest</title>
-</head>
-<body>
- 
-<h1>ModalBlockedStealsFocusTest<br>Bug ID: 6426132</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=ModalBlockedStealsFocusTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,38 +22,30 @@
  */
 
 /*
-  test
-  @bug       6426132
-  @summary   Modal blocked window shouldn't steal focus when shown, or brought to front.
-  @author    anton.tarasov@...: area=awt.focus
-  @run       applet ModalBlockedStealsFocusTest.html
+  @test
+  @key headful
+  @bug        6426132
+  @summary    Modal blocked window shouldn't steal focus when shown, or brought to front.
+  @library    ../../regtesthelpers
+  @build      Util
+  @run        main ModalBlockedStealsFocusTest
 */
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class ModalBlockedStealsFocusTest extends Applet {
+public class ModalBlockedStealsFocusTest {
     Frame frame = new Frame("Blocked Frame");
     Dialog dialog = new Dialog(frame, "Modal Dialog", Dialog.ModalityType.TOOLKIT_MODAL);
     AtomicBoolean lostFocus = new AtomicBoolean(false);
 
     public static void main(String[] args) {
         ModalBlockedStealsFocusTest app = new ModalBlockedStealsFocusTest();
-        app.init();
         app.start();
     }
 
-    public void init() {
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
-    }
-
     public void start() {
         if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) {
             System.out.println("The test is not for MToolkit.");
--- a/test/jdk/java/awt/Focus/ModalDialogInitialFocusTest/ModalDialogInitialFocusTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2006, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6382750
-  @summary
-  @author     anton.tarasov@sun.com: area=awt.focus
-  @run        applet ModalDialogInitialFocusTest.html
-  -->
-<head>
-<title>ModalDialogInitialFocusTest</title>
-</head>
-<body>
- 
-<h1>ModalDialogInitialFocusTest<br>Bug ID: 6382750</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=ModalDialogInitialFocusTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/ModalDialogInitialFocusTest/ModalDialogInitialFocusTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ModalDialogInitialFocusTest/ModalDialogInitialFocusTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,20 +22,17 @@
  */
 
 /*
-  test
-  @bug       6382750
+  @test
+  @key headful
+  @bug        6382750
   @summary   Tests that modal dialog doesn't request extra initial focus on show.
-  @author    anton.tarasov@sun.com: area=awt.focus
-  @run       applet ModalDialogInitialFocusTest.html
+  @run        main ModalDialogInitialFocusTest
 */
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 
-public class ModalDialogInitialFocusTest extends Applet {
+public class ModalDialogInitialFocusTest {
     Robot robot;
 
     Dialog dialog = new Dialog((Window)null, "Test Dialog", Dialog.ModalityType.TOOLKIT_MODAL);
@@ -55,10 +52,6 @@
         } catch (AWTException e) {
             throw new RuntimeException("Error: unable to create robot", e);
         }
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
--- a/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<!--
- Copyright (c) 2005, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug        6271849
-  @summary    Tests that component in modal excluded Window which parent is blocked responses to mouse clicks.
-  @author     anton.tarasov@sun.com: area=awt.focus
-  @modules java.desktop/sun.awt
-  @run        applet ModalExcludedWindowClickTest.html
-  -->
-<head>
-<title>ModalExcludedWindowClickTest</title>
-</head>
-<body>
-
-<h1>ModalExcludedWindowClickTest<br>Bug ID: 6272324</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="ModalExcludedWindowClickTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,19 +22,19 @@
  */
 
 /*
-  test
-  @bug       6271849
-  @summary   Tests that component in modal excluded Window which parent is blocked responses to mouse clicks.
-  @author    anton.tarasov@sun.com: area=awt.focus
-  @run       applet ModalExcludedWindowClickTest.html
+  @test
+  @key headful
+  @bug        6271849
+  @summary    Tests that component in modal excluded Window which parent is blocked responses to mouse clicks.
+  @modules java.desktop/sun.awt
+  @run        main ModalExcludedWindowClickTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import java.lang.reflect.*;
 
-public class ModalExcludedWindowClickTest extends Applet {
+public class ModalExcludedWindowClickTest {
     Robot robot;
     Frame frame = new Frame("Frame");
     Window w = new Window(frame);
@@ -54,10 +54,6 @@
         } catch (AWTException e) {
             throw new RuntimeException("Error: unable to create robot", e);
         }
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
--- a/test/jdk/java/awt/Focus/NoAutotransferToDisabledCompTest/NoAutotransferToDisabledCompTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/NoAutotransferToDisabledCompTest/NoAutotransferToDisabledCompTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,7 +26,6 @@
   @key headful
   @bug       4685768
   @summary   Tests that auto-transfering focus doesn't stuck on a disabled component.
-  @author    Anton Tarasov: area=awt.focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main NoAutotransferToDisabledCompTest
@@ -36,10 +35,9 @@
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 import test.java.awt.regtesthelpers.Util;
 
-public class NoAutotransferToDisabledCompTest extends Applet {
+public class NoAutotransferToDisabledCompTest {
     Robot robot;
     JFrame frame = new JFrame("Frame");
     JButton b0 = new JButton("b0");
--- a/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<!--
- Copyright (c) 2005, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug        6272324
-  @summary    Modal excluded Window which decorated parent is blocked should be non-focusable.
-  @author     anton.tarasov@sun.com: area=awt.focus
-  @modules java.desktop/sun.awt
-  @run        applet NonFocusableBlockedOwnerTest.html
-  -->
-<head>
-<title>NonFocusableBlockedOwnerTest</title>
-</head>
-<body>
-
-<h1>NonFocusableBlockedOwnerTest<br>Bug ID: 6272324</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="NonFocusableBlockedOwnerTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,19 +22,19 @@
  */
 
 /*
-  test
-  @bug       6272324
-  @summary   Modal excluded Window which decorated parent is blocked should be non-focusable.
-  @author    anton.tarasov@sun.com: area=awt.focus
-  @run       applet NonFocusableBlockedOwnerTest.html
+  @test
+  @key headful
+  @bug        6272324
+  @summary    Modal excluded Window which decorated parent is blocked should be non-focusable.
+  @modules java.desktop/sun.awt
+  @run        main NonFocusableBlockedOwnerTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import java.lang.reflect.*;
 
-public class NonFocusableBlockedOwnerTest extends Applet {
+public class NonFocusableBlockedOwnerTest {
     Robot robot;
     Frame frame = new Frame("Modal Blocked Frame");
     Dialog dialog = new Dialog(frame, "Modal Dialog", true);
@@ -53,10 +53,6 @@
         } catch (AWTException e) {
             throw new RuntimeException("Error: unable to create robot", e);
         }
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
--- a/test/jdk/java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,7 +26,6 @@
   @key headful
   @bug       6182359
   @summary   Tests that Window having non-focusable owner can't be a focus owner.
-  @author    Anton.Tarasov: area=awt.focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main NonfocusableOwnerTest
@@ -34,12 +33,9 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
-import java.lang.reflect.*;
-import java.io.*;
 import test.java.awt.regtesthelpers.Util;
 
-public class NonfocusableOwnerTest extends Applet {
+public class NonfocusableOwnerTest {
     Robot robot = Util.createRobot();
     Frame frame;
     Dialog dialog;
--- a/test/jdk/java/awt/Focus/NullActiveWindowOnFocusLost/NullActiveWindowOnFocusLost.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/NullActiveWindowOnFocusLost/NullActiveWindowOnFocusLost.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@
  * @test
  * @key headful
  * @bug 8211435
- * @requires (os.family == "mac")
  * @modules java.desktop/sun.awt
  */
 public final class NullActiveWindowOnFocusLost {
--- a/test/jdk/java/awt/Focus/RequestFocusToDisabledCompTest/RequestFocusToDisabledCompTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/RequestFocusToDisabledCompTest/RequestFocusToDisabledCompTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,7 +26,6 @@
   @key headful
   @bug       4685768
   @summary   Tests that it's possible to manually request focus on a disabled component.
-  @author    Anton Tarasov: area=awt.focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main RequestFocusToDisabledCompTest
@@ -35,11 +34,9 @@
 import java.awt.Robot;
 import javax.swing.*;
 import java.awt.*;
-import java.awt.event.*;
-import java.applet.Applet;
 import test.java.awt.regtesthelpers.Util;
 
-public class RequestFocusToDisabledCompTest extends Applet {
+public class RequestFocusToDisabledCompTest {
     Robot robot;
     JFrame frame = new JFrame("Frame");
     JButton b0 = new JButton("b0");
--- a/test/jdk/java/awt/Focus/ResetMostRecentFocusOwnerTest/ResetMostRecentFocusOwnerTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ResetMostRecentFocusOwnerTest/ResetMostRecentFocusOwnerTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -26,15 +26,12 @@
   @key headful
   @bug      8013773
   @summary  Tests that disabled component is not retained as most recent focus owner.
-  @author   Anton.Tarasov: area=awt.focus
   @library  ../../regtesthelpers
   @build    Util
   @run      main ResetMostRecentFocusOwnerTest
 */
 
-import java.applet.Applet;
 import java.awt.AWTEvent;
-import java.awt.FlowLayout;
 import java.awt.Robot;
 import java.awt.Toolkit;
 import java.awt.event.AWTEventListener;
@@ -44,15 +41,13 @@
 import javax.swing.JFrame;
 import test.java.awt.regtesthelpers.Util;
 
-public class ResetMostRecentFocusOwnerTest extends Applet {
+public class ResetMostRecentFocusOwnerTest {
 
     public static void main(String[] args) {
         ResetMostRecentFocusOwnerTest app = new ResetMostRecentFocusOwnerTest();
-        app.init();
         app.start();
     }
 
-    @Override
     public void start() {
 
         Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@@ -68,7 +63,7 @@
         final JButton b1 = new JButton("button1");
         frame1.add(b1);
         frame1.pack();
-        frame1.setLocation(0, 300);
+        frame1.setLocation(100, 300);
 
         Util.showWindowWait(frame1);
 
--- a/test/jdk/java/awt/Focus/RestoreFocusOnDisabledComponentTest/RestoreFocusOnDisabledComponentTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/RestoreFocusOnDisabledComponentTest/RestoreFocusOnDisabledComponentTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,11 +22,10 @@
  */
 
 /*
-  @test      %W% %E%
+  @test
   @key headful
   @bug       6598089
   @summary   Tests restoring focus on a single disabled coponent
-  @author    Anton Tarasov: area=awt-focus
   @library   ../../regtesthelpers
   @build     Util
   @run       main RestoreFocusOnDisabledComponentTest
@@ -34,13 +33,12 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 import test.java.awt.regtesthelpers.Util;
 
 /*
  * The bug is not reproducible on Windows.
  */
-public class RestoreFocusOnDisabledComponentTest extends Applet {
+public class RestoreFocusOnDisabledComponentTest {
     Frame frame = new Frame("Frame") {public String toString() {return "FRAME";}};
     Button b0 = new Button("button0") {public String toString() {return "B-0";}};
     Button b1 = new Button("button1") {public String toString() {return "B-1";}};
@@ -62,7 +60,7 @@
         frame.add(b1);
         frame.setLayout(new FlowLayout());
         frame.pack();
-
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
 
         Util.waitForIdle(robot);
--- a/test/jdk/java/awt/Focus/ShowFrameCheckForegroundTest/ShowFrameCheckForegroundTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ShowFrameCheckForegroundTest/ShowFrameCheckForegroundTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -28,18 +28,14 @@
   @summary   Tests that showing a toplvel in a not foreground Java process activates it.
   @library   ../../regtesthelpers
   @build     Util
-  @author    Anton Tarasov: area=awt-focus
   @run       main ShowFrameCheckForegroundTest
  */
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class ShowFrameCheckForegroundTest extends Applet {
+public class ShowFrameCheckForegroundTest {
     Robot robot;
     Frame nofocusFrame = new Frame("Non-focusable");
     Frame frame = new Frame("Frame");
@@ -76,6 +72,7 @@
         nofocusFrame.add(showButton);
         nofocusFrame.pack();
         nofocusFrame.setFocusableWindowState(false);
+        nofocusFrame.setLocation(200, 200);
         nofocusFrame.setVisible(true);
         Util.waitForIdle(robot);
 
@@ -97,7 +94,7 @@
     private void test(Window toplevel, int stage) {
         toplevel.add(testButton);
         toplevel.pack();
-        toplevel.setLocation(200, 0);
+        toplevel.setLocation(400, 200);
 
         switch (stage) {
             case 1:
--- a/test/jdk/java/awt/Focus/ToFrontFocusTest/ToFrontFocus.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<!--
- Copyright (c) 2002, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4092033 4529626
-  @summary Tests that toFront makes window focused unless it is non-focusable
-  @author  area=awt.focus
-  @library ../../regtesthelpers
-  @build Util
-  @run applet ToFrontFocus.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>ToFrontFocus<br>
-4092033 : (P4/S5) - window.toFront() method is now also setting focus
-4529626 : (P4/S2) - REGRESSION:In solaris and Linux ,toFront() is not making frame as the Focused.
-</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="ToFrontFocus.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/ToFrontFocusTest/ToFrontFocus.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/ToFrontFocusTest/ToFrontFocus.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,39 +22,32 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4092033 4529626
   @summary Tests that toFront makes window focused unless it is non-focusable
-  @author  area=awt.focus
-  @run applet ToFrontFocus.html
+  @library ../../regtesthelpers
+  @build Util
+  @run main ToFrontFocus
 */
 
-/**
- * ToFrontFocus.java
- *
- * summary:
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import test.java.awt.regtesthelpers.Util;
 
-public class ToFrontFocus extends Applet
- {
-   //Declare things used in the test, like buttons and labels here
-
+public class ToFrontFocus {
      Frame cover, focus_frame, nonfocus_frame;
      Button focus_button, nonfocus_button;
      volatile boolean focus_gained = false, nonfocus_gained = false;
-   public void init()
+
+    public static void main(final String[] args) {
+        ToFrontFocus app = new ToFrontFocus();
+        app.init();
+        app.start();
+    }
+
+    public void init()
     {
-      //Create instructions for the user here, as well as set up
-      // the environment -- set the layout manager, add buttons,
-      // etc.
-
-      this.setLayout (new BorderLayout ());
-
       cover = new Frame("Cover frame");
       cover.setBounds(100, 100, 200, 200);
       focus_frame = new Frame("Focusable frame");
@@ -78,9 +71,6 @@
 
    public void start ()
     {
-      //Get things going.  Request focus, set size, et cetera
-      setSize (200,200);
-      show();
       Util.waitForIdle(null);
 
       focus_frame.setFocusTraversalPolicy(new DefaultFocusTraversalPolicy() {
--- a/test/jdk/java/awt/Focus/WindowInitialFocusTest/WindowInitialFocusTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- Copyright (c) 2006, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6426132
-  @summary    A Window should be focused upon start (XAWT bug).
-  @author     anton.tarasov@...: area=awt.focus
-  @library    ../../regtesthelpers        
-  @build      Util        
-  @run        applet WindowInitialFocusTest.html
-  -->
-<head>
-<title>WindowInitialFocusTest</title>
-</head>
-<body>
- 
-<h1>WindowInitialFocusTest<br>Bug ID: 6426132</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=WindowInitialFocusTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/WindowInitialFocusTest/WindowInitialFocusTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/WindowInitialFocusTest/WindowInitialFocusTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,20 +22,21 @@
  */
 
 /*
-  test
-  @bug       6426132
-  @summary   A Window should be initially focused on its showing (XAWT bug).
-  @author    anton.tarasov@...: area=awt.focus
-  @run       applet WindowInitialFocusTest.html
+  @test
+  @key headful
+  @bug        6426132
+  @summary    A Window should be focused upon start (XAWT bug).
+  @library    ../../regtesthelpers
+  @build      Util
+  @run        main WindowInitialFocusTest
 */
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 import java.util.concurrent.atomic.AtomicBoolean;
 import test.java.awt.regtesthelpers.Util;
 
-public class WindowInitialFocusTest extends Applet {
+public class WindowInitialFocusTest {
     Frame frame = new Frame("Test Frame");
     Window window = new Window(frame);
     Button button = new Button("button");
@@ -44,17 +45,9 @@
 
     public static void main(String[] args) {
         WindowInitialFocusTest app = new WindowInitialFocusTest();
-        app.init();
         app.start();
     }
 
-    public void init() {
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
-    }
-
     public void start() {
         frame.setBounds(800, 0, 200, 100);
         window.setBounds(800, 200, 200, 100);
--- a/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<!--
- Copyright (c) 2005, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6253913
-  @summary    Tests that a Window shown before its owner is focusable.
-  @author     anton.tarasov@sun.com: area=awt-focus
-  @modules java.desktop/sun.awt
-  @run        applet WindowUpdateFocusabilityTest.html
-  -->
-<head>
-<title>WindowUpdateFocusabilityTest</title>
-</head>
-<body>
- 
-<h1>WindowUpdateFocusabilityTest<br>Bug ID: 6253913</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=WindowUpdateFocusabilityTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,19 +22,19 @@
  */
 
 /*
-  test
-  @bug       6253913
-  @summary   Tests that a Window shown before its owner is focusable.
-  @author    anton.tarasov@sun.com: area=awt-focus
-  @run       applet WindowUpdateFocusabilityTest.html
+  @test
+  @key headful
+  @bug        6253913
+  @summary    Tests that a Window shown before its owner is focusable.
+  @modules java.desktop/sun.awt
+  @run        main WindowUpdateFocusabilityTest
 */
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 import java.lang.reflect.*;
 
-public class WindowUpdateFocusabilityTest extends Applet {
+public class WindowUpdateFocusabilityTest {
     Robot robot;
     boolean focusGained = false;
     final Object monitor = new Object();
@@ -60,10 +60,6 @@
         } catch (AWTException e) {
             throw new RuntimeException("Error: couldn't create robot");
         }
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
--- a/test/jdk/java/awt/Focus/WrongKeyTypedConsumedTest/WrongKeyTypedConsumedTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Focus/WrongKeyTypedConsumedTest/WrongKeyTypedConsumedTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,24 +26,15 @@
   @key headful
   @bug      4782886
   @summary  FocusManager consumes wrong KEY_TYPED events
-  @author   Oleg.Sukhodolsky: area=awt.focus
   @library  ../../regtesthelpers
   @build    Util
   @run      main WrongKeyTypedConsumedTest
 */
 
-import java.applet.Applet;
-import java.awt.AWTException;
 import java.awt.AWTKeyStroke;
 import java.awt.BorderLayout;
-import java.awt.Dialog;
-import java.awt.Dimension;
-import java.awt.FlowLayout;
-import java.awt.Frame;
 import java.awt.KeyboardFocusManager;
-import java.awt.Point;
 import java.awt.Robot;
-import java.awt.TextArea;
 
 import java.awt.event.KeyEvent;
 
@@ -56,7 +47,7 @@
 
 import test.java.awt.regtesthelpers.Util;
 
-public class WrongKeyTypedConsumedTest extends Applet
+public class WrongKeyTypedConsumedTest
 {
     Robot robot = Util.createRobot();
 
@@ -67,10 +58,6 @@
 
     public void start ()
     {
-        setSize (200,200);
-        setVisible(true);
-        validate();
-
         JFrame frame = new JFrame("The Frame");
         Set ftk = new HashSet();
         ftk.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_DOWN, 0));
@@ -85,6 +72,7 @@
         frame.getContentPane().add(textarea);
 
         frame.pack();
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
         Util.waitForIdle(robot);
 
--- a/test/jdk/java/awt/FontClass/CreateFont/BigFont.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/FontClass/CreateFont/BigFont.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -21,12 +21,23 @@
  * questions.
  */
 
-import java.applet.*;
-import java.awt.*;
-import java.io.*;
-import java.net.*;
+import java.awt.Font;
+import java.awt.FontFormatException;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Paths;
 
-public class BigFont extends Applet {
+/**
+ * @test
+ * @key headful
+ * @bug 6522586
+ * @summary Enforce limits on font creation
+ * @run main BigFont 1 A.ttf
+ * @run main BigFont 2 A.ttf
+ */
+public class BigFont {
 
    static private class SizedInputStream extends InputStream {
 
@@ -51,12 +62,12 @@
        }
    }
 
-    String id;
-    String fileName;
+    static String id;
+    static String fileName;
 
-    public void init() {
-        id = getParameter("number");
-        fileName = getParameter("font");
+    public static void main(final String[] args) {
+        id = args[0];
+        fileName = args[1];
 
         System.out.println("Applet " + id + " "+
                            Thread.currentThread().getThreadGroup());
@@ -102,7 +113,10 @@
 
     int getFileSize(String fileName) {
         try {
-            URL url = new URL(getCodeBase(), fileName);
+            String path = Paths.get(System.getProperty("test.src", "."),
+                                    fileName).toAbsolutePath().normalize()
+                                             .toString();
+            URL url = new URL(path);
             InputStream inStream = url.openStream();
             BufferedInputStream fontStream = new BufferedInputStream(inStream);
             int size = 0;
@@ -123,7 +137,10 @@
         boolean gotException = false;
         for (int i=0; i<fontCnt; i++) {
             try {
-                URL url = new URL(getCodeBase(), fileName);
+                String path = Paths.get(System.getProperty("test.src", "."),
+                                        fileName).toAbsolutePath().normalize()
+                                                 .toString();
+                URL url = new URL(path);
                 InputStream inStream = url.openStream();
                 BufferedInputStream fontStream =
                     new BufferedInputStream(inStream);
--- a/test/jdk/java/awt/FontClass/CreateFont/bigfont.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<!--
-
- Copyright (c) 2008, 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
-  @key headful
-  @bug 6522586
-  @run applet bigfont.html
-  @summary Enforce limits on font creation
-
--->
-
-<html>
-  <head>
-      <title>Test Font Creation Limits</title>
-  </head>
-  <body>
-<hr>
-<APPLET CODE = BigFont.class WIDTH = 100 HEIGHT = 100 >
-<param name="number" value="1">
-<param name="font" value="A.ttf">
-</APPLET>
-<APPLET CODE = BigFont.class WIDTH = 100 HEIGHT = 100>
-<param name="number" value="2">
-<param name="font" value="A.ttf">
-</APPLET>
-<hr>
-  </body>
-</html>
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/awt/FontMetrics/MaxAdvanceIsMax.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc.
+ * 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 8218854
+ * @requires jdk.version.major >= 8
+ * @run main/othervm MaxAdvanceIsMax
+ */
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class MaxAdvanceIsMax {
+
+    private static boolean debug = true;
+
+    private static final class AntialiasHint {
+        private Object aaHint;
+        private String asString = "";
+
+        AntialiasHint(Object aaHint) {
+            if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)) {
+                asString += "FT_LOAD_TARGET_MONO";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_ON)) {
+                asString += "FT_LOAD_TARGET_NORMAL";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB)) {
+                asString += "FT_LOAD_TARGET_LCD";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB)) {
+                asString += "FT_LOAD_TARGET_LCD_V";
+            }
+            this.aaHint = aaHint;
+        }
+
+        public Object getHint() {
+            return aaHint;
+        }
+
+        public String toString() {
+            return asString;
+        }
+    }
+
+    private static final AntialiasHint[] antialiasHints = {
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_ON),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB)
+    };
+
+    private static final class StyleAndSize {
+        int style;
+        float size;
+        public StyleAndSize(int style, float size) {
+            this.style = style;
+            this.size = size;
+        }
+    };
+
+    private static final StyleAndSize[] stylesAndSizes = new StyleAndSize[] {
+        new StyleAndSize(Font.BOLD | Font.ITALIC, 10)
+    };
+
+    public static void main(String[] args) throws Exception {
+        GraphicsEnvironment e =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+        Font[] fonts = e.getAllFonts();
+        BufferedImage bi = new BufferedImage(500, 500,
+                BufferedImage.TYPE_INT_RGB);
+        for (AntialiasHint antialiasHint : antialiasHints) {
+            for (Font f : fonts) {
+                for (StyleAndSize styleAndSize : stylesAndSizes) {
+                    f = f.deriveFont(styleAndSize.style, styleAndSize.size);
+                    Graphics2D g2d = bi.createGraphics();
+                    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+                            antialiasHint.getHint());
+                    FontMetrics fm = g2d.getFontMetrics(f);
+                    int[] width;
+                    int maxWidth = -1;
+                    int maxAdvance = fm.getMaxAdvance();
+                    if (debug) {
+                        System.out.println("Testing " + f + " in " +
+                                antialiasHint);
+                        System.out.println("getMaxAdvance: " + maxAdvance);
+                    }
+                    if (maxAdvance != -1) {
+                        String failureMessage = null;
+                        width = fm.getWidths();
+                        for (int j = 0; j < width.length; j++) {
+                            if (width[j] > maxWidth) {
+                                maxWidth = width[j];
+                            }
+                            if (width[j] > maxAdvance) {
+                                failureMessage = "FAILED: getMaxAdvance is " +
+                                                 "not max for font: " +
+                                                 f.toString() +
+                                                 " getMaxAdvance(): " +
+                                                 maxAdvance +
+                                                 " getWidths()[" + j + "]: " +
+                                                 width[j];
+                                throw new Exception(failureMessage);
+                            }
+                        }
+                    }
+                    if (debug) {
+                        System.out.println("Max char width: " + maxWidth);
+                        System.out.println("PASSED");
+                        System.out.println(".........................");
+                    }
+                }
+            }
+        }
+        System.out.println("TEST PASS - OK");
+    }
+}
--- a/test/jdk/java/awt/Frame/DisposeStressTest/DisposeStressTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4051487 4145670
-  @summary Tests that disposing of an empty Frame or a Frame with a MenuBar
-           while it is being created does not crash the VM.
-  @author dpm area=Threads
-  @run applet/timeout=7200 DisposeStressTest.html
-  -->
-<head>
-<title>DisposeStressTest</title>
-</head>
-<body>
-
-<h1>DisposeStressTest<br>Bug ID: 4051487, 4145670</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="DisposeStressTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Frame/DisposeStressTest/DisposeStressTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Frame/DisposeStressTest/DisposeStressTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -21,67 +21,23 @@
  * questions.
  */
 
-
 /*
-  test
-  @bug 4051487 4145670 8062021
+  @test
+  @key headful
+  @bug 4051487 4145670
   @summary Tests that disposing of an empty Frame or a Frame with a MenuBar
            while it is being created does not crash the VM.
-  @author dpm area=Threads
-  @run applet/timeout=7200 DisposeStressTest.html
+  @run main/timeout=7200 DisposeStressTest
 */
 
-// Note there is no @ in front of test above.  This is so that the
-//  harness will not mistake this file as a test file.  It should
-//  only see the html file as a test file. (the harness runs all
-//  valid test files, so it would run this test twice if this file
-//  were valid as well as the html file.)
-// Also, note the area= after Your Name in the author tag.  Here, you
-//  should put which functional area the test falls in.  See the
-//  AWT-core home page -> test areas and/or -> AWT team  for a list of
-//  areas.
-// Note also the 'DisposeStressTest.html' in the run tag.  This should
-//  be changed to the name of the test.
-
-
-/**
- * DisposeStressTest.java
- *
- * summary:
- */
-
-import java.applet.Applet;
-import java.awt.*;
-
+import java.awt.Frame;
+import java.awt.Menu;
+import java.awt.MenuBar;
+import java.awt.MenuItem;
 
-//Automated tests should run as applet tests if possible because they
-// get their environments cleaned up, including AWT threads, any
-// test created threads, and any system resources used by the test
-// such as file descriptors.  (This is normally not a problem as
-// main tests usually run in a separate VM, however on some platforms
-// such as the Mac, separate VMs are not possible and non-applet
-// tests will cause problems).  Also, you don't have to worry about
-// synchronisation stuff in Applet tests they way you do in main
-// tests...
-
+public class DisposeStressTest {
 
-public class DisposeStressTest extends Applet
- {
-   //Declare things used in the test, like buttons and labels here
-
-   public void init()
-    {
-      //Create instructions for the user here, as well as set up
-      // the environment -- set the layout manager, add buttons,
-      // etc.
-
-      this.setLayout (new BorderLayout ());
-
-
-    }//End  init()
-
-   public void start ()
-    {
+    public static void main(final String[] args) {
         for (int i = 0; i < 1000; i++) {
             Frame f = new Frame();
             f.setBounds(10, 10, 10, 10);
@@ -98,6 +54,5 @@
             f2.show();
             f2.dispose();
         }
-    }// start()
-
- }// class DisposeStressTest
+    }
+}
--- a/test/jdk/java/awt/Frame/NonEDT_GUI_DeadlockTest/NonEDT_GUI_Deadlock.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<html>
-<!--
- Copyright (c) 2003, 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
-  @key headful
-  @bug 4828019
-  @summary Frame/Window deadlock
-  @author yan@sparc.spb.su: area=
-  @run applet/timeout=9999 NonEDT_GUI_Deadlock.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>NonEDT_GUI_Deadlock<br>Bug ID: 4828019</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="NonEDT_GUI_Deadlock.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Frame/NonEDT_GUI_DeadlockTest/NonEDT_GUI_Deadlock.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Frame/NonEDT_GUI_DeadlockTest/NonEDT_GUI_Deadlock.java	Tue Mar 26 09:05:10 2019 -0400
@@ -21,70 +21,22 @@
  * questions.
  */
 
-
 /*
-  test
+  @test
+  @key headful
   @bug 4828019
   @summary Frame/Window deadlock
-  @author yan@sparc.spb.su: area=
-  @run applet NonEDT_GUI_Deadlock.html
+  @run main/timeout=9999 NonEDT_GUI_Deadlock
 */
 
-// Note there is no @ in front of test above.  This is so that the
-//  harness will not mistake this file as a test file.  It should
-//  only see the html file as a test file. (the harness runs all
-//  valid test files, so it would run this test twice if this file
-//  were valid as well as the html file.)
-// Also, note the area= after Your Name in the author tag.  Here, you
-//  should put which functional area the test falls in.  See the
-//  AWT-core home page -> test areas and/or -> AWT team  for a list of
-//  areas.
-// Note also the 'AutomaticAppletTest.html' in the run tag.  This should
-//  be changed to the name of the test.
-
-
-/**
- * NonEDT_GUI_Deadlock.java
- *
- * summary:
- */
+import java.awt.*;
 
-import java.applet.Applet;
-import java.awt.*;
-import java.awt.event.*;
-import java.net.*;
-import java.io.*;
-
-
-//Automated tests should run as applet tests if possible because they
-// get their environments cleaned up, including AWT threads, any
-// test created threads, and any system resources used by the test
-// such as file descriptors.  (This is normally not a problem as
-// main tests usually run in a separate VM, however on some platforms
-// such as the Mac, separate VMs are not possible and non-applet
-// tests will cause problems).  Also, you don't have to worry about
-// synchronisation stuff in Applet tests they way you do in main
-// tests...
-
-
-public class NonEDT_GUI_Deadlock extends Applet
-{
-    //Declare things used in the test, like buttons and labels here
+public class NonEDT_GUI_Deadlock {
     boolean bOK = false;
     Thread badThread = null;
 
-    public void init()
-    {
-    }//End  init()
-
     public void start ()
     {
-        //Get things going.  Request focus, set size, et cetera
-
-        setSize (200,300);
-        setVisible(true);
-        validate();
-
         final Frame theFrame = new Frame("Window test");
         theFrame.setSize(240, 200);
 
@@ -164,7 +116,6 @@
 
     public static void main(String args[]) {
        NonEDT_GUI_Deadlock imt = new NonEDT_GUI_Deadlock();
-       imt.init();
        imt.start();
     }
 
--- a/test/jdk/java/awt/FullScreen/SetFSWindow/FSFrame.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/FullScreen/SetFSWindow/FSFrame.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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,12 +30,10 @@
  * on older Gnome versions (see bug 6500686).
  * @run main FSFrame
  * @run main/othervm -Dsun.java2d.noddraw=true FSFrame
- * @author cheth
  */
 
 import java.awt.*;
 import java.awt.image.*;
-import java.applet.*;
 import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
--- a/test/jdk/java/awt/GridBagLayout/GridBagLayoutIpadXYTest/GridBagLayoutIpadXYTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<html>
-<!--  
-
- Copyright (c) 2009, 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
-  @key headful
-  @bug 5004032
-  @summary GridBagConstraints.ipad(x|y) defined in a new way
-  @author dav@sparc.spb.su area= 
-  @run applet GridBagLayoutIpadXYTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>GridBagLayoutIpadXYTest<br>Bug ID: 5004032 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="GridBagLayoutIpadXYTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/GridBagLayout/GridBagLayoutIpadXYTest/GridBagLayoutIpadXYTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/GridBagLayout/GridBagLayoutIpadXYTest/GridBagLayoutIpadXYTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,32 +22,22 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 5004032
   @summary GridBagConstraints.ipad(x|y) defined in a new way
-  @author dav@sparc.spb.su area=
-  @run applet GridBagLayoutIpadXYTest.html
+  @run main GridBagLayoutIpadXYTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 
-public class GridBagLayoutIpadXYTest extends Applet
-{
-    Frame frame = new Frame();
-    TextField jtf = null;
-    final int customIpadx = 300;
-    final int customIpady = 40;
+public class GridBagLayoutIpadXYTest {
+    static Frame frame = new Frame();
+    static TextField jtf = null;
+    static final int customIpadx = 300;
+    static final int customIpady = 40;
 
-    public void init()
-    {
-        this.setLayout (new BorderLayout ());
-
-    }//End  init()
-
-    public void start ()
-    {
-        validate();
+    public static void main(final String[] args) {
         frame.setLayout(new GridBagLayout());
         GridBagConstraints gc = new GridBagConstraints();
         Insets fieldInsets = new Insets(0,5,5,0);
@@ -64,6 +54,7 @@
         frame.add(jtf, gc);
 
         frame.pack();
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
 
         Robot robot;
@@ -86,6 +77,5 @@
             throw new RuntimeException("Test Failed. TextField has incorrect width. ");
         }
         System.out.println("Test Passed.");
-
-    }// start()
+    }
 }
--- a/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2006, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6391688
-  @summary    Tests that next mnemonic KeyTyped is consumed for a modal dialog.
-  @author     anton.tarasov@sun.com: area=awt.focus
-  @run        applet ConsumeForModalDialogTest.html
-  -->
-<head>
-<title>ConsumeForModalDialogTest</title>
-</head>
-<body>
- 
-<h1>ConsumeForModalDialogTest<br>Bug ID: 6391688</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=ConsumeForModalDialogTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -20,22 +20,20 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 /*
-  test
-  @bug       6391688
-  @summary   Tests that next mnemonic KeyTyped is consumed for a modal dialog.
-  @author    anton.tarasov@sun.com: area=awt.focus
-  @run       applet ConsumeForModalDialogTest.html
+  @test
+  @key headful
+  @bug        6391688
+  @summary    Tests that next mnemonic KeyTyped is consumed for a modal dialog.
+  @run        main ConsumeForModalDialogTest
 */
 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 
-public class ConsumeForModalDialogTest extends Applet {
+public class ConsumeForModalDialogTest {
     Robot robot;
     JFrame frame = new JFrame("Test Frame");
     JDialog dialog = new JDialog((Window)null, "Test Dialog", Dialog.ModalityType.DOCUMENT_MODAL);
@@ -55,10 +53,6 @@
         } catch (AWTException e) {
             throw new RuntimeException("Error: unable to create robot", e);
         }
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
@@ -93,6 +87,7 @@
 
         frame.setJMenuBar(menuBar);
         frame.setSize(100, 100);
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
 
         robot.waitForIdle();
--- a/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- 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
- 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6346690
-  @summary    Tests that key_typed is consumed after mnemonic key_pressed is handled for a menu item.
-  @author     anton.tarasov@sun.com: area=awt-focus
-  @library    /test/lib
-  @build      jdk.test.lib.Platform
-  @run        applet ConsumeNextMnemonicKeyTypedTest.html
-  -->
-<head>
-<title>ConsumeNextMnemonicKeyTypedTest</title>
-</head>
-<body>
- 
-<h1>ConsumeNextMnemonicKeyTypedTest<br>Bug ID: 6346690</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=ConsumeNextMnemonicKeyTypedTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,13 +22,13 @@
  */
 
 /*
-  test
-  @bug       6346690
-  @summary   Tests that key_typed is consumed after mnemonic key_pressed is handled for a menu item.
-  @author    anton.tarasov@sun.com: area=awt-focus
-  @library   /test/lib
-  @build     jdk.test.lib.Platform
-  @run       applet ConsumeNextMnemonicKeyTypedTest.html
+  @test
+  @key headful
+  @bug        6346690
+  @summary    Tests that key_typed is consumed after mnemonic key_pressed is handled for a menu item.
+  @library    /test/lib
+  @build      jdk.test.lib.Platform
+  @run        main ConsumeNextMnemonicKeyTypedTest
 */
 
 import jdk.test.lib.Platform;
@@ -36,10 +36,8 @@
 import java.awt.*;
 import javax.swing.*;
 import java.awt.event.*;
-import java.applet.Applet;
 
-
-public class ConsumeNextMnemonicKeyTypedTest extends Applet {
+public class ConsumeNextMnemonicKeyTypedTest {
     Robot robot;
     JFrame frame = new JFrame("Test Frame");
     JTextField text = new JTextField();
@@ -60,10 +58,6 @@
         } catch (AWTException e) {
             throw new RuntimeException("Error: unable to create robot", e);
         }
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
@@ -76,7 +70,7 @@
         frame.setJMenuBar(bar);
         frame.pack();
 
-        frame.setLocation(800, 0);
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
 
         test();
--- a/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- Copyright (c) 2006, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6396785
-  @summary    Action key pressed on a button should be swallowed.
-  @author     anton.tarasov@...: area=awt.focus
-  @library    ../../../regtesthelpers
-  @build      Util
-  @run        applet ButtonActionKeyTest.html
-  -->
-<head>
-<title>ButtonActionKeyTest</title>
-</head>
-<body>
- 
-<h1>ButtonActionKeyTest<br>Bug ID: 6396785</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=ButtonActionKeyTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,22 +22,22 @@
  */
 
 /*
-  test
-  @bug       6396785
-  @summary   Action key pressed on a button should be swallowed.
-  @author    anton.tarasov@...: area=awt.focus
-  @run       applet ButtonActionKeyTest.html
+  @test
+  @key headful
+  @bug        6396785
+  @summary    Action key pressed on a button should be swallowed.
+  @library    ../../../regtesthelpers
+  @build      Util
+  @run        main ButtonActionKeyTest
 */
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import java.applet.Applet;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class ButtonActionKeyTest extends Applet {
+public class ButtonActionKeyTest {
     Robot robot;
     JFrame frame = new JFrame("Frame");
     JButton button = new JButton("button");
@@ -52,11 +52,6 @@
 
     public void init() {
         robot = Util.createRobot();
-
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
@@ -84,7 +79,7 @@
                     }
                 }
             });
-
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
         Util.waitForIdle(robot);
 
--- a/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/MenuItemActivatedTest/MenuItemActivatedTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- Copyright (c) 2006, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug        6396785
-  @summary    MenuItem activated with space should swallow this space.
-  @author     anton.tarasov@...: area=awt.focus
-  @library    ../../../regtesthelpers
-  @build      Util
-  @run        applet MenuItemActivatedTest.html
-  -->
-<head>
-<title>MenuItemActivatedTest</title>
-</head>
-<body>
- 
-<h1>MenuItemActivatedTest<br>Bug ID: 6396785</h1>
- 
-<p>See the dialog box (usually in upper left corner) for instructions</p>
- 
-<APPLET CODE=MenuItemActivatedTest.class WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/MenuItemActivatedTest/MenuItemActivatedTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/MenuItemActivatedTest/MenuItemActivatedTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,22 +22,22 @@
  */
 
 /*
-  test
-  @bug       6396785
-  @summary   MenuItem activated with space should swallow this space.
-  @author    anton.tarasov@...: area=awt.focus
-  @run       applet MenuItemActivatedTest.html
+  @test
+  @key headful
+  @bug        6396785
+  @summary    MenuItem activated with space should swallow this space.
+  @library    ../../../regtesthelpers
+  @build      Util
+  @run        main MenuItemActivatedTest
 */
 
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.*;
-import java.applet.Applet;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.lang.reflect.InvocationTargetException;
 import test.java.awt.regtesthelpers.Util;
 
-public class MenuItemActivatedTest extends Applet {
+public class MenuItemActivatedTest {
     Robot robot;
     JFrame frame = new JFrame("Test Frame");
     JDialog dialog = new JDialog((Window)null, "Test Dialog", Dialog.ModalityType.DOCUMENT_MODAL);
@@ -55,11 +55,6 @@
 
     public void init() {
         robot = Util.createRobot();
-
-        // Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout (new BorderLayout ());
     }
 
     public void start() {
@@ -68,6 +63,7 @@
         bar.add(menu);
         frame.setJMenuBar(bar);
         frame.pack();
+        frame.setLocationRelativeTo(null);
 
         item.addActionListener(new ActionListener() {
                 public void actionPerformed(ActionEvent ae) {
--- a/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-<!--
- Copyright (c) 2003, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4799136
-  @summary Tests that type-ahead for dialog works and doesn't block program
-  @author  area=awt.focus
-  @library    ../../regtesthelpers
-  @modules java.desktop/sun.awt
-  @build      Util        
-  @run applet TestDialogTypeAhead.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>TestDialogTypeAhead<br>Bug ID: 4799136 Tests that type-ahead for dialog works and doesn't block program   </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="TestDialogTypeAhead.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,51 +22,21 @@
  */
 
 /*
-test
-@bug 4799136
-@summary Tests that type-ahead for dialog works and doesn't block program
-@author  area=awt.focus
-@run applet TestDialogTypeAhead.html
+  @test
+  @key headful
+  @bug 4799136
+  @summary Tests that type-ahead for dialog works and doesn't block program
+  @library    ../../regtesthelpers
+  @modules java.desktop/sun.awt
+  @build      Util
+  @run main TestDialogTypeAhead
 */
 
-// Note there is no @ in front of test above.  This is so that the
-//  harness will not mistake this file as a test file.  It should
-//  only see the html file as a test file. (the harness runs all
-//  valid test files, so it would run this test twice if this file
-//  were valid as well as the html file.)
-// Also, note the area= after Your Name in the author tag.  Here, you
-//  should put which functional area the test falls in.  See the
-//  AWT-core home page -> test areas and/or -> AWT team  for a list of
-//  areas.
-// Note also the 'TestDialogTypeAhead.html' in the run tag.  This should
-//  be changed to the name of the test.
-
-
-/**
- * TestDialogTypeAhead.java
- *
- * summary:
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import java.lang.reflect.InvocationTargetException;
-import test.java.awt.regtesthelpers.Util;
 
-//Automated tests should run as applet tests if possible because they
-// get their environments cleaned up, including AWT threads, any
-// test created threads, and any system resources used by the test
-// such as file descriptors.  (This is normally not a problem as
-// main tests usually run in a separate VM, however on some platforms
-// such as the Mac, separate VMs are not possible and non-applet
-// tests will cause problems).  Also, you don't have to worry about
-// synchronisation stuff in Applet tests they way you do in main
-// tests...
-
-
-public class TestDialogTypeAhead extends Applet
-{
+public class TestDialogTypeAhead {
     //Declare things used in the test, like buttons and labels here
     static Frame f;
     static Button b;
@@ -76,12 +46,15 @@
     static Semaphore robotSema = new Semaphore();
     static volatile boolean gotFocus = false;
     static Robot robot;
+
+    public static void main(final String[] args) {
+        TestDialogTypeAhead app = new TestDialogTypeAhead();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
-        //Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-
         Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
                 public void eventDispatched(AWTEvent e) {
                     System.err.println(e.toString());
@@ -90,8 +63,6 @@
 
         KeyboardFocusManager.setCurrentKeyboardFocusManager(new TestKFM());
 
-        this.setLayout (new BorderLayout ());
-
         f = new Frame("frame");
         b = new Button("press");
         d = new Dialog(f, "dialog", true);
@@ -139,16 +110,12 @@
 
     public void start ()
     {
-        //Get things going.  Request focus, set size, et cetera
-        setSize (200,200);
-        setVisible(true);
-        validate();
         try {
             robot = new Robot();
         } catch (Exception e) {
             throw new RuntimeException("Can't create robot:" + e);
         }
-
+        f.setLocationRelativeTo(null);
         f.setVisible(true);
         waitTillShown(b);
         System.err.println("b is shown");
--- a/test/jdk/java/awt/List/FirstItemRemoveTest/FirstItemRemoveTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<html>
-<!--
-  Copyright (c) 2013, 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
-  @key headful
-  @bug 6299858
-  @summary PIT. Focused border not shown on List if selected item is removed, XToolkit
-  @author Dmitry.Cherepanov@SUN.COM area=awt.list
-  @library /test/lib
-  @build jdk.test.lib.Platform
-  @run applet FirstItemRemoveTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>FirstItemRemoveTest<br>Bug ID: 6299858 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="FirstItemRemoveTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/List/FirstItemRemoveTest/FirstItemRemoveTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/List/FirstItemRemoveTest/FirstItemRemoveTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,24 +22,31 @@
  */
 
 /*
-  test
-  @bug 6299858 7124338
+  @test
+  @key headful
+  @bug 6299858
   @summary PIT. Focused border not shown on List if selected item is removed, XToolkit
-  @author Dmitry.Cherepanov@SUN.COM area=awt.list
-  @run applet FirstItemRemoveTest.html
+  @library /test/lib
+  @build jdk.test.lib.Platform
+  @run main FirstItemRemoveTest
 */
 
 import jdk.test.lib.Platform;
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 
-public class FirstItemRemoveTest extends Applet
+public class FirstItemRemoveTest extends Frame
 {
     List list = new List(4, false);
     Panel panel = new Panel();
 
+    public static void main(final String[] args) {
+        FirstItemRemoveTest app = new FirstItemRemoveTest();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
         list.add("000");
@@ -59,6 +66,8 @@
     public void start ()
     {
         setSize (200,200);
+        setUndecorated(true);
+        setLocationRelativeTo(null);
         setVisible(true);
         validate();
 
--- a/test/jdk/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-<!--
- Copyright (c) 2007, 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.
--->
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6387275
-  @summary List: the focus is at the top of the first item, XAWT
-  @author Dmitry.Cherepanov@SUN.COM area=awt.list
-  @requires (os.family == "linux" | os.family == "solaris")
-  @modules java.desktop/sun.awt
-           java.desktop/java.awt.peer
-           java.desktop/sun.awt.X11:open
-  @run applet FocusEmptyListTest.html
-  -->
-<head>
-<title> FocusEmptyListTest </title>
-</head>
-<body>
-
-<h1>FocusEmptyListTest<br>Bug ID: 6387275 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="FocusEmptyListTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/List/FocusEmptyListTest/FocusEmptyListTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -22,25 +22,29 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6387275
   @summary List: the focus is at the top of the first item, XAWT
-  @author Dmitry.Cherepanov@SUN.COM area=awt.list
-  @run applet FocusEmptyListTest.html
+  @requires (os.family == "linux" | os.family == "solaris")
+  @modules java.desktop/sun.awt
+           java.desktop/java.awt.peer
+           java.desktop/sun.awt.X11:open
+  @run main FocusEmptyListTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.lang.reflect.*;
 import java.awt.peer.ListPeer;
 
 import sun.awt.AWTAccessor;
 
-public class FocusEmptyListTest extends Applet {
+public class FocusEmptyListTest extends Frame {
 
-    public void init() {
-        setLayout(new BorderLayout());
-    }//End  init()
+    public static void main(final String[] args) {
+        FocusEmptyListTest app = new FocusEmptyListTest();
+        app.start();
+    }
 
     public void start() {
         boolean isXToolkit = Toolkit.getDefaultToolkit()
@@ -61,6 +65,8 @@
         list.add("item1");
 
         setSize(200, 200);
+        setUndecorated(true);
+        setLocationRelativeTo(null);
         setVisible(true);
         validate();
 
--- a/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2005, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6190768 6190778
-  @summary Tests that triggering events on AWT list by pressing CTRL + HOME, CTRL + END, PG-UP, PG-DOWN similar Motif behavior
-  @author Dmitry.Cherepanov@SUN.COM area=awt.list
-  @library /test/lib
-  @build jdk.test.lib.Platform
-  @run applet KeyEventsTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>KeyEventsTest<br>Bug ID: 6190768 6190778 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="KeyEventsTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/List/KeyEventsTest/KeyEventsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,30 +22,23 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6190768 6190778
-  @summary Tests that triggering events on AWT list by pressing CTRL + HOME, CTRL + END, PG-UP, PG-DOWN similar Motif behavior
-  @author Dmitry.Cherepanov@SUN.COM area=awt.list
+  @summary Tests that triggering events on AWT list by pressing CTRL + HOME,
+           CTRL + END, PG-UP, PG-DOWN similar Motif behavior
   @library /test/lib
   @build jdk.test.lib.Platform
-  @run applet KeyEventsTest.html
+  @run main KeyEventsTest
 */
 
-/**
- * KeyEventsTest.html
- *
- * summary:
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
-import java.util.Set;
 import java.lang.reflect.*;
 
 import jdk.test.lib.Platform;
 
-public class KeyEventsTest extends Applet implements ItemListener, FocusListener, KeyListener
+public class KeyEventsTest extends Frame implements ItemListener, FocusListener, KeyListener
 {
     TestState currentState;
     final Object LOCK = new Object();
@@ -57,6 +50,12 @@
     Panel p1 = new Panel ();
     Panel p2 = new Panel ();
 
+    public static void main(final String[] args) {
+        KeyEventsTest app = new KeyEventsTest();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
         setLayout (new BorderLayout ());
@@ -100,11 +99,13 @@
 
         try{
             setSize (200,200);
+            validate();
+            setUndecorated(true);
+            setLocationRelativeTo(null);
             setVisible(true);
-            validate();
 
-            main(null);
-
+            doTest();
+            System.out.println("Test passed.");
         } catch (Exception e) {
             e.printStackTrace();
             throw new RuntimeException("The test failed.");
@@ -112,14 +113,6 @@
 
     }// start()
 
-    private void main(String[] args)
-      throws InterruptedException, InvocationTargetException {
-
-        doTest();
-
-        System.out.println("Test passed.");
-    }
-
     public void itemStateChanged (ItemEvent ie) {
         System.out.println("itemStateChanged-"+ie);
         this.currentState.setAction(true);
--- a/test/jdk/java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- Copyright (c) 2005, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 5039416 6404008
-  @summary REGRESSION: Extra mouse click dispatched after press-drag- release sequence.
-  @library ../../regtesthelpers
-  @build Util
-  @author andrei.dmitriev area=awt.event
-  @run applet ExtraMouseClick.html
-  -->
-<head>
-<title>ExtraMouseClick </title>
-</head>
-<body>
-
-<h1>ExtraMouseClick<br>Bug ID: 5039416 </h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="ExtraMouseClick.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Mouse/ExtraMouseClick/ExtraMouseClick.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -22,18 +22,16 @@
  */
 
  /*
-  test
-  @bug 5039416 6404008 7087869
+  @test
+  @key headful
+  @bug 5039416 6404008
   @summary REGRESSION: Extra mouse click dispatched after press-drag- release sequence.
   @library ../../regtesthelpers
   @build Util
-  @author  andrei.dmitriev area=awt.event
-  @run applet ExtraMouseClick.html
+  @run main ExtraMouseClick
  */
 
-import java.applet.Applet;
 import java.awt.AWTException;
-import java.awt.BorderLayout;
 import java.awt.Frame;
 import java.awt.Point;
 import java.awt.Robot;
@@ -50,9 +48,7 @@
 // Note that this test may not fail easily. But it must always pass on
 // patched workspace.
 //**
-
-public class ExtraMouseClick extends Applet
-{
+public class ExtraMouseClick {
     Frame frame = new Frame("Extra Click After MouseDrag");
     final int TRIALS = 10;
     final int SMUDGE_WIDTH = 4;
@@ -64,10 +60,14 @@
     boolean pressed = false;
     boolean released = false;
 
+    public static void main(final String[] args) {
+        ExtraMouseClick app = new ExtraMouseClick();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
-        this.setLayout (new BorderLayout ());
-
         frame.addMouseListener(new MouseAdapter() {
                 public void mousePressed(MouseEvent e) {
                     System.out.println("MousePressed");
@@ -99,6 +99,7 @@
     public void start ()
     {
         frame.setSize(480, 300);
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
         try{
             robot = new Robot();
--- a/test/jdk/java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2002, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4664415
-  @summary Test that double clicking the titlebar does not send RELEASE/CLICKED
-  @library    ../../regtesthelpers
-  @build      Util        
-  @author bchristi: area=Mouse 
-  @run applet TitleBarDoubleClick.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>TitleBarDoubleClick<br>Bug ID: 9999999 XXX_CHANGE_THIS </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="TitleBarDoubleClick.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Mouse/TitleBarDoubleClick/TitleBarDoubleClick.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 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
@@ -22,18 +22,20 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4664415
-  @summary REGRESSION: double click jframe titlebar generating mouse events in panel
-  @author Andrei Dmitriev: area=awt.mouse
-  @run applet TitleBarDoubleClick.html
+  @summary Test that double clicking the titlebar does not send RELEASE/CLICKED
+  @library    ../../regtesthelpers
+  @build      Util
+  @run main TitleBarDoubleClick
 */
-import java.applet.Applet;
+
 import java.awt.*;
 import java.awt.event.*;
 import test.java.awt.regtesthelpers.Util;
 
-public class TitleBarDoubleClick extends Applet implements MouseListener,
+public class TitleBarDoubleClick implements MouseListener,
  WindowListener
 {
     //Declare things used in the test, like buttons and labels here
@@ -43,24 +45,13 @@
     Frame frame;
     Robot robot;
 
-    public void init()
-    {
-        this.setLayout (new BorderLayout ());
-
-    }//End  init()
+    public static void main(final String[] args) {
+        TitleBarDoubleClick app = new TitleBarDoubleClick();
+        app.start();
+    }
 
     public void start ()
     {
-        //Get things going.  Request focus, set size, et cetera
-        setSize (200,200);
-        setVisible(true);
-        validate();
-
-        //What would normally go into main() will probably go here.
-        //Use System.out.println for diagnostic messages that you want
-        //to read after the test is done.
-        //Use Sysout.println for messages you want the tester to read.
-
             robot = Util.createRobot();
             robot.setAutoDelay(100);
             robot.mouseMove(BOUNDS.x + (BOUNDS.width / 2),
--- a/test/jdk/java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-<!--
- Copyright (c) 2005, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4868278
-  @summary Tests that GraphicsConfig for invisible (peerless) windows is
-updated after showing the window
-  @author artem.ananiev, area=awt.multiscreen
-  @library ../../regtesthelpers
-  @build Util
-  @run applet WindowGCChangeTest.html
-  -->
-<head>
-<title> WindowGCChangeTest </title>
-</head>
-<body>
-
-<h1>WindowGCChangeTest<br>Bug ID: 4868278 Problem with Action button tooltips with some multiple monitor configurations </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="WindowGCChangeTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -22,31 +22,24 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4868278
-  @summary Tests that GraphicsConfig for invisible (peerless) window is
-   updated after showing the window
-  @author artem.ananiev, area=awt.multiscreen
+  @summary Tests that GraphicsConfig for invisible (peerless) windows is
+           updated after showing the window
   @library ../../regtesthelpers
   @build Util
-  @run applet WindowGCChangeTest.html
+  @run main WindowGCChangeTest
 */
 
-import java.applet.Applet;
-
 import java.awt.*;
 import java.awt.event.*;
 
 import test.java.awt.regtesthelpers.Util;
 
-public class WindowGCChangeTest extends Applet
-{
-    public void init()
-    {
-    }
+public class WindowGCChangeTest {
 
-    public void start()
-    {
+    public static void main(final String[] args) {
         Robot robot = null;
         try
         {
@@ -57,10 +50,6 @@
             z.printStackTrace(System.err);
             throw new RuntimeException("Test FAILED: couldn't create Robot instance", z);
         }
-
-        setSize(200, 200);
-        setVisible(true);
-        validate();
         Util.waitForIdle(robot);
 
         GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
--- a/test/jdk/java/awt/Window/HandleWindowDestroyTest/HandleWindowDestroyTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6260648
-  @summary Tests that WINDOW_DESTROY event can be handled by overriding handleEvent(). Also,
-tests that handleEvent() is not called by AWT if any listener is added to the component
-(i. e. when post-1.1 events schema is used)
-  @author artem.ananiev: area=awt.event
-  @run applet HandleWindowDestroyTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>HandleWindowDestroyTest<br>Bug ID: 6260648</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="HandleWindowDestroyTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/Window/HandleWindowDestroyTest/HandleWindowDestroyTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/Window/HandleWindowDestroyTest/HandleWindowDestroyTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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,30 +24,23 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6260648
   @summary Tests that WINDOW_DESTROY event can be handled by overriding handleEvent(). Also,
 tests that handleEvent() is not called by AWT if any listener is added to the component
 (i. e. when post-1.1 events schema is used)
-  @author artem.ananiev: area=awt.event
-  @run applet HandleWindowDestroyTest.html
+  @run main HandleWindowDestroyTest
 */
 
-import java.applet.*;
-
 import java.awt.*;
 import java.awt.event.*;
 
-public class HandleWindowDestroyTest extends Applet
-{
-    private volatile boolean handleEventCalled;
+public class HandleWindowDestroyTest {
 
-    public void start ()
-    {
-        setSize (200,200);
-        setVisible(true);
-        validate();
+    private static volatile boolean handleEventCalled;
 
+    public static void main(final String[] args) {
         Robot robot;
         try {
             robot = new Robot();
--- a/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<!--
- Copyright (c) 2009, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 5098433
-  @summary REG: DnD of File-List between JVM is broken for non ASCII file names - Win32
-  @author Denis Fokin: area=dnd
-  @library ../../regtesthelpers
-  @library ../../regtesthelpers/process
-  @build Util
-  @build ProcessResults ProcessCommunicator 
-  @run applet/othervm DragUnicodeBetweenJVMTest.html
-
--->
-<head>
-<title> REG: DnD of File-List between JVM is broken for non ASCII file names - Win32</title>
-</head>
-<body>
-
-<h1> DragUnicodeBetweenJVMTest <br>Bug ID: 5098433 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="DragUnicodeBetweenJVMTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 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
@@ -22,43 +22,26 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 5098433
   @summary REG: DnD of File-List between JVM is broken for non ASCII file names - Win32
-  @author Denis Fokin: area=dnd
-  @library    ../../regtesthelpers
+  @library ../../regtesthelpers
   @library ../../regtesthelpers/process
   @build Util
   @build ProcessResults ProcessCommunicator
-
-
-  @run applet/othervm DragUnicodeBetweenJVMTest.html
+  @run main/othervm DragUnicodeBetweenJVMTest main
 */
 
-/**
- * DragUnicodeBetweenJVMTest.java
- *
- * summary: The test drags a list of files (DataFlavor.javaFileListFlavor) from one jvm to another.
- *          The files have Unicode names. The list on target side must be equal to
- *          the list on the source side.
- */
-
-
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 
 import test.java.awt.regtesthelpers.process.ProcessCommunicator;
 import test.java.awt.regtesthelpers.process.ProcessResults;
 import test.java.awt.regtesthelpers.Util;
 import static java.lang.Thread.sleep;
 
-public class DragUnicodeBetweenJVMTest extends Applet
-{
-
-    public void init() {
-        setLayout(new BorderLayout());
-    }//End  init()
+public class DragUnicodeBetweenJVMTest {
 
     public void start() {
 
@@ -176,7 +159,11 @@
         }
     }
 
-    public static void main (String [] args) {
+    public static void main(final String [] args) {
+        if (args.length > 0 && args[0].equals("main")) {
+            new DragUnicodeBetweenJVMTest().start();
+            return;
+        }
         Point dragSourcePoint = new Point(InterprocessArguments.DRAG_SOURCE_POINT_X_ARGUMENT.extract(args),
                 InterprocessArguments.DRAG_SOURCE_POINT_Y_ARGUMENT.extract(args));
         Point targetFrameLocation = new Point(InterprocessArguments.TARGET_FRAME_X_POSITION_ARGUMENT.extract(args),
@@ -188,6 +175,4 @@
             e.printStackTrace();
         }
     }
-
-
 }
--- a/test/jdk/java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-<!--
- Copyright (c) 2013, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 8005932 8017456
-  @summary Java 7 on mac os x only provides text clipboard formats
-  @author mikhail.cherkasov@oracle.com
-  @library ../../regtesthelpers
-  @library ../../regtesthelpers/process
-  @library /test/lib
-  @build Util
-  @build ProcessResults ProcessCommunicator
-  @build jdk.test.lib.Platform
-  @run applet/othervm MissedHtmlAndRtfBug.html
--->
-
-<head>
-    <title>Java 7 on mac os x only provides text clipboard formats</title>
-</head>
-<body>
-
-<h1> MissedHtmlAndRtfBug <br>Bug ID: 8005932 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="MissedHtmlAndRtfBug.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java	Tue Mar 26 09:05:10 2019 -0400
@@ -24,7 +24,6 @@
 import java.awt.*;
 import java.awt.datatransfer.DataFlavor;
 import java.awt.event.*;
-import java.applet.Applet;
 import java.io.File;
 import java.util.ArrayList;
 
@@ -35,11 +34,20 @@
 
 import static java.lang.Thread.sleep;
 
-public class MissedHtmlAndRtfBug extends Applet {
-
-    public void init() {
-        setLayout(new BorderLayout());
-    }//End  init()
+/*
+    @test
+    @key headful
+    @bug 8005932 8017456
+    @summary Java 7 on mac os x only provides text clipboard formats
+    @library ../../regtesthelpers
+    @library ../../regtesthelpers/process
+    @library /test/lib
+    @build Util
+    @build ProcessResults ProcessCommunicator
+    @build jdk.test.lib.Platform
+    @run main/othervm MissedHtmlAndRtfBug main
+ */
+public class MissedHtmlAndRtfBug {
 
     public void start() {
         if (!Platform.isOSX() && !Platform.isWindows()) {
@@ -178,6 +186,11 @@
     }
 
     public static void main(String[] args) throws InterruptedException {
+        if (args.length > 0 && args[0].equals("main")) {
+            new MissedHtmlAndRtfBug().start();
+            return;
+        }
+
         Point dragSourcePoint = new Point(InterprocessArguments.DRAG_SOURCE_POINT_X_ARGUMENT.extractInt(args),
                 InterprocessArguments.DRAG_SOURCE_POINT_Y_ARGUMENT.extractInt(args));
         Point targetFrameLocation = new Point(InterprocessArguments.TARGET_FRAME_X_POSITION_ARGUMENT.extractInt(args),
--- a/test/jdk/java/awt/dnd/DragInterceptorAppletTest/DragInterceptorAppletTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<!--
- Copyright (c) 2014, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6887703
-  @summary Unsigned applet can retrieve the dragged information before drop action occurs
-  @author : area=dnd
-  @library ../../regtesthelpers
-  @library ../../regtesthelpers/process
-  @build Util
-  @build ProcessResults ProcessCommunicator 
-  @run applet/othervm DragInterceptorAppletTest.html
-
--->
-<head>
-<title> Unsigned applet can retrieve the dragged information before drop action occurs </title>
-</head>
-<body>
-
-<h1>DragInterceptorAppletTest<br>Bug ID: 6887703</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="DragInterceptorAppletTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/dnd/DragInterceptorAppletTest/DragInterceptorAppletTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/dnd/DragInterceptorAppletTest/DragInterceptorAppletTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -22,33 +22,28 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6887703
   @summary Unsigned applet can retrieve the dragged information before drop action occurs
-  @author : area=dnd
-  @run applet DragInterceptorAppletTest.html
+  @library ../../regtesthelpers
+  @library ../../regtesthelpers/process
+  @build Util
+  @build ProcessResults ProcessCommunicator
+  @run main/othervm DragInterceptorAppletTest main
 */
 
-/**
- * DragInterceptorAppletTest.java
- *
- * summary: Unsigned applet can retrieve the dragged information before drop action occurs
- */
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+
+import test.java.awt.regtesthelpers.Util;
+import test.java.awt.regtesthelpers.process.ProcessCommunicator;
+import test.java.awt.regtesthelpers.process.ProcessResults;
 
 import static java.lang.Thread.sleep;
 
-import test.java.awt.regtesthelpers.process.ProcessCommunicator;
-import test.java.awt.regtesthelpers.process.ProcessResults;
-import test.java.awt.regtesthelpers.Util;
-import java.applet.Applet;
-import java.awt.*;
-import java.awt.event.InputEvent;
-
-public class DragInterceptorAppletTest extends Applet {
-
-    public void init() {
-        setLayout(new BorderLayout());
-    }//End  init()
+public class DragInterceptorAppletTest {
 
     public void start() {
 
@@ -138,7 +133,11 @@
         }
     }
 
-    public static void main (String [] args) {
+    public static void main(final String[] args) {
+        if (args.length > 0 && args[0].equals("main")) {
+            new DragInterceptorAppletTest().start();
+            return;
+        }
         Point dragSourcePoint = new Point(InterprocessArguments.DRAG_SOURCE_POINT_X_ARGUMENT.extract(args),
                 InterprocessArguments.DRAG_SOURCE_POINT_Y_ARGUMENT.extract(args));
         Point targetFrameLocation = new Point(InterprocessArguments.TARGET_FRAME_X_POSITION_ARGUMENT.extract(args),
--- a/test/jdk/java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<!--
- Copyright (c) 2007, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 5079469
-  @summary DnD of File-List across JVM adds two empty items to the list
-  @author : area=dnd
-  @library ../../regtesthelpers
-  @library ../../regtesthelpers/process
-  @build Util
-  @build ProcessResults ProcessCommunicator 
-  @run applet/othervm FileListBetweenJVMsTest.html
-
--->
-<head>
-<title> DnD of File-List across JVM </title>
-</head>
-<body>
-
-<h1>FileListBetweenJVMsTest<br>Bug ID: 5079469</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="FileListBetweenJVMsTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/dnd/FileListBetweenJVMsTest/FileListBetweenJVMsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -22,39 +22,30 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 5079469
   @summary DnD of File-List across JVM adds two empty items to the list
-  @author : area=dnd
-  @run applet FileListBetweenJVMsTest.html
+  @library ../../regtesthelpers
+  @library ../../regtesthelpers/process
+  @build Util
+  @build ProcessResults ProcessCommunicator
+  @run main/othervm FileListBetweenJVMsTest main
 */
 
-/**
- * FileListBetweenJVMsTest.java
- *
- * summary: DnD of File-List across JVM adds two empty items to the list
- */
-
 import static java.lang.Thread.sleep;
 
 import test.java.awt.regtesthelpers.process.ProcessCommunicator;
 import test.java.awt.regtesthelpers.process.ProcessResults;
 import test.java.awt.regtesthelpers.Util;
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.InputEvent;
-import java.io.*;
 
-public class FileListBetweenJVMsTest extends Applet {
+public class FileListBetweenJVMsTest {
 
     // information related to the test in common
     static int VISIBLE_RAWS_IN_LIST=15;
 
-    public void init() {
-        setLayout(new BorderLayout());
-
-    }//End  init()
-
     public void start() {
 
         SourceFileListFrame sourceFrame = new SourceFileListFrame();
@@ -130,7 +121,11 @@
         }
     }
 
-    public static void main (String [] args) {
+    public static void main(final String [] args) {
+        if (args.length > 0 && args[0].equals("main")) {
+            new FileListBetweenJVMsTest().start();
+            return;
+        }
         Point dragSourcePoint = new Point(InterprocessArguments.DRAG_SOURCE_POINT_X_ARGUMENT.extract(args),
                 InterprocessArguments.DRAG_SOURCE_POINT_Y_ARGUMENT.extract(args));
         Point targetFrameLocation = new Point(InterprocessArguments.TARGET_FRAME_X_POSITION_ARGUMENT.extract(args),
--- a/test/jdk/java/awt/dnd/ImageDecoratedDnDInOut/ImageDecoratedDnDInOut.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2009, 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.
--->
-
-<html>
-<!--
-  @test %W% %E%
-  @key headful
-  @bug 4874070
-  @summary Tests basic DnD functionality
-  @author Your Name: Alexey Utkin area=dnd
-  @run applet ImageDecoratedDnDInOut.html
-  -->
-<head>
-    <title> ImageDecoratedDnDInOut </title>
-</head>
-<body>
-
-<h1>ImageDecoratedDnDInOut<br>Bug ID: 4874070</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="ImageDecoratedDnDInOut.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/dnd/ImageDecoratedDnDInOut/ImageDecoratedDnDInOut.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/dnd/ImageDecoratedDnDInOut/ImageDecoratedDnDInOut.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, 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
@@ -22,56 +22,44 @@
  */
 
 /*
-  test %W% %E%
+  @test
+  @key headful
   @bug 4874070
   @summary Tests basic DnD functionality
-  @author Your Name: Alexey Utkin area=dnd
-  @run applet ImageDecoratedDnDInOut.html
+  @run main ImageDecoratedDnDInOut
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.Robot;
 import java.awt.event.InputEvent;
 import java.awt.dnd.DragSource;
 
-
-public class ImageDecoratedDnDInOut extends Applet {
-    //Declare things used in the test, like buttons and labels here
-
-    public void init() {
-        //Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout(new BorderLayout());
+/*
+    "Automatic test.",
+    "A Frame, which contains a yellow button labeled \"Drag ME!\" and ",
+    "a red panel, will appear below. ",
+    "1. The button would be clicked and dragged to the red panel. ",
+    "2. When the mouse enters the red panel during the drag, the panel ",
+    "should turn yellow. On the systems that supports pictured drag, ",
+    "the image under the drag-cursor should appear (ancor is shifted ",
+    "from top-left corner of the picture inside the picture to 10pt in both dimensions ). ",
+    "In WIN32 systems the image under cursor would be visible ONLY over ",
+    "the drop targets with activated extended OLE D\'n\'D support (that are ",
+    "the desktop and IE ).",
+    "3. The mouse would be released.",
+    "The panel should turn red again and a yellow button labeled ",
+    "\"Drag ME!\" should appear inside the panel. "
+ */
+public class ImageDecoratedDnDInOut {
 
-        String[] instructions =
-                {
-                        "Automatic test.",
-                        "A Frame, which contains a yellow button labeled \"Drag ME!\" and ",
-                        "a red panel, will appear below. ",
-                        "1. The button would be clicked and dragged to the red panel. ",
-                        "2. When the mouse enters the red panel during the drag, the panel ",
-                        "should turn yellow. On the systems that supports pictured drag, ",
-                        "the image under the drag-cursor should appear (ancor is shifted ",
-                        "from top-left corner of the picture inside the picture to 10pt in both dimensions ). ",
-                        "In WIN32 systems the image under cursor would be visible ONLY over ",
-                        "the drop targets with activated extended OLE D\'n\'D support (that are ",
-                        "the desktop and IE ).",
-                        "3. The mouse would be released.",
-                        "The panel should turn red again and a yellow button labeled ",
-                        "\"Drag ME!\" should appear inside the panel. "
-                };
-        Sysout.createDialogWithInstructions(instructions);
-
-    }//End  init()
-
-    public void start() {
+    public static void main(final String[] args) {
         Frame f = new Frame("Use keyboard for DnD change");
         Panel mainPanel;
         Component dragSource, dropTarget;
 
-        f.setBounds(0, 400, 200, 200);
+        f.setSize(200, 200);
+        f.setUndecorated(true);
+        f.setLocationRelativeTo(null);
         f.setLayout(new BorderLayout());
 
         mainPanel = new Panel();
@@ -93,6 +81,7 @@
             sourcePoint.translate(d.width / 2, d.height / 2);
 
             Robot robot = new Robot();
+            robot.waitForIdle();
             robot.mouseMove(sourcePoint.x, sourcePoint.y);
             robot.mousePress(InputEvent.BUTTON1_MASK);
             Thread.sleep(2000);
@@ -121,112 +110,5 @@
             throw new RuntimeException("test failed: drop was not successful with exception " + e);
         }
 
-    }// start()
+    }
 }// class DnDAcceptanceTest
-
-
-/**
- * *************************************************
- * Standard Test Machinery
- * DO NOT modify anything below -- it's a standard
- * chunk of code whose purpose is to make user
- * interaction uniform, and thereby make it simpler
- * to read and understand someone else's test.
- * **************************************************
- */
-class Sysout {
-    private static TestDialog dialog;
-
-    public static void createDialogWithInstructions(String[] instructions) {
-        dialog = new TestDialog(new Frame(), "Instructions");
-        dialog.printInstructions(instructions);
-        dialog.show();
-        println("Any messages for the tester will display here.");
-    }
-
-    public static void createDialog() {
-        dialog = new TestDialog(new Frame(), "Instructions");
-        String[] defInstr = {"Instructions will appear here. ", ""};
-        dialog.printInstructions(defInstr);
-        dialog.show();
-        println("Any messages for the tester will display here.");
-    }
-
-
-    public static void printInstructions(String[] instructions) {
-        dialog.printInstructions(instructions);
-    }
-
-
-    public static void println(String messageIn) {
-        dialog.displayMessage(messageIn);
-    }
-
-}// Sysout  class
-
-
-class TestDialog extends Dialog {
-
-    TextArea instructionsText;
-    TextArea messageText;
-    int maxStringLength = 80;
-
-    //DO NOT call this directly, go through Sysout
-    public TestDialog(Frame frame, String name) {
-        super(frame, name);
-        int scrollBoth = TextArea.SCROLLBARS_BOTH;
-        instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
-        add("North", instructionsText);
-
-        messageText = new TextArea("", 5, maxStringLength, scrollBoth);
-        add("South", messageText);
-
-        pack();
-
-        show();
-    }// TestDialog()
-
-    //DO NOT call this directly, go through Sysout
-    public void printInstructions(String[] instructions) {
-        //Clear out any current instructions
-        instructionsText.setText("");
-
-        //Go down array of instruction strings
-
-        String printStr, remainingStr;
-        for (int i = 0; i < instructions.length; i++) {
-            //chop up each into pieces maxSringLength long
-            remainingStr = instructions[i];
-            while (remainingStr.length() > 0) {
-                //if longer than max then chop off first max chars to print
-                if (remainingStr.length() >= maxStringLength) {
-                    //Try to chop on a word boundary
-                    int posOfSpace = remainingStr.
-                            lastIndexOf(' ', maxStringLength - 1);
-
-                    if (posOfSpace <= 0) posOfSpace = maxStringLength - 1;
-
-                    printStr = remainingStr.substring(0, posOfSpace + 1);
-                    remainingStr = remainingStr.substring(posOfSpace + 1);
-                }
-                //else just print
-                else {
-                    printStr = remainingStr;
-                    remainingStr = "";
-                }
-
-                instructionsText.append(printStr + "\n");
-
-            }// while
-
-        }// for
-
-    }//printInstructions()
-
-    //DO NOT call this directly, go through Sysout
-    public void displayMessage(String messageIn) {
-        messageText.append(messageIn + "\n");
-    }
-
-}// TestDialog  class
-
--- a/test/jdk/java/awt/dnd/ImageDecoratedDnDNegative/ImageDecoratedDnDNegative.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2009, 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.
--->
-
-<html>
-<!--
-  @test %W% %E%
-  @key headful
-  @bug 4874070
-  @summary Tests basic DnD functionality
-  @author Your Name: Alexey Utkin area=dnd
-  @run applet ImageDecoratedDnDNegative.html
-  -->
-<head>
-    <title> ImageDecoratedDnDNegative </title>
-</head>
-<body>
-
-<h1>ImageDecoratedDnDInOut<br>Bug ID: 4874070</h1>
-
-<p> See the dialog box (usually in upper left corner) for the test description</p>
-
-<APPLET CODE="ImageDecoratedDnDNegative.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/dnd/ImageDecoratedDnDNegative/ImageDecoratedDnDNegative.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/dnd/ImageDecoratedDnDNegative/ImageDecoratedDnDNegative.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, 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
@@ -22,14 +22,13 @@
  */
 
 /*
-  test %W% %E%
-  @bug 4874070 7146550
+  @test
+  @key headful
+  @bug 4874070
   @summary Tests basic DnD functionality
-  @author Your Name: Alexey Utkin area=dnd
-  @run applet ImageDecoratedDnDNegative.html
+  @run main ImageDecoratedDnDNegative
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.Robot;
 import java.awt.event.InputEvent;
@@ -39,39 +38,26 @@
 
 import java.awt.dnd.DragSource;
 
-
-public class ImageDecoratedDnDNegative extends Applet {
-    //Declare things used in the test, like buttons and labels here
-
-    public void init() {
-        //Create instructions for the user here, as well as set up
-        // the environment -- set the layout manager, add buttons,
-        // etc.
-        this.setLayout(new BorderLayout());
+/*
+    "Automatic test.",
+    "A Frame, which contains a yellow button labeled \"Drag ME!\" and ",
+    "a red panel, will appear below. ",
+    "1. The button would be clicked and dragged to the red panel. ",
+    "2. When the mouse enters the red panel during the drag, the panel ",
+    "should turn yellow. On the systems that supports pictured drag, ",
+    "the image under the drag-cursor should appear (ancor is shifted ",
+    "from top-left corner of the picture inside the picture to 10pt in both dimensions ). ",
+    "In WIN32 systems the image under cursor would be visible ONLY over ",
+    "the drop targets with activated extended OLE D\'n\'D support (that are ",
+    "the desktop and IE ).",
+    "3. The mouse would be released.",
+    "The panel should turn red again and a yellow button labeled ",
+    "\"Drag ME!\" should appear inside the panel. You should be able ",
+    "to repeat this operation multiple times."
+ */
+public class ImageDecoratedDnDNegative {
 
-        String[] instructions =
-                {
-                        "Automatic test.",
-                        "A Frame, which contains a yellow button labeled \"Drag ME!\" and ",
-                        "a red panel, will appear below. ",
-                        "1. The button would be clicked and dragged to the red panel. ",
-                        "2. When the mouse enters the red panel during the drag, the panel ",
-                        "should turn yellow. On the systems that supports pictured drag, ",
-                        "the image under the drag-cursor should appear (ancor is shifted ",
-                        "from top-left corner of the picture inside the picture to 10pt in both dimensions ). ",
-                        "In WIN32 systems the image under cursor would be visible ONLY over ",
-                        "the drop targets with activated extended OLE D\'n\'D support (that are ",
-                        "the desktop and IE ).",
-                        "3. The mouse would be released.",
-                        "The panel should turn red again and a yellow button labeled ",
-                        "\"Drag ME!\" should appear inside the panel. You should be able ",
-                        "to repeat this operation multiple times."
-                };
-        Sysout.createDialogWithInstructions(instructions);
-
-    }//End  init()
-
-    public void moveTo(
+    public static void moveTo(
         Robot r,
         Point b,
         Point e)
@@ -95,7 +81,7 @@
         r.delay(5);
     }
 
-    public void start() {
+    public static void main(final String[] args) {
         Frame f = new Frame("Use keyboard for DnD change");
         Panel mainPanel;
         Component dragSource, dropTarget;
@@ -114,7 +100,8 @@
         mainPanel.add(dragSource, "North");
         mainPanel.add(dropTarget, "Center");
         f.add(mainPanel, BorderLayout.CENTER);
-
+        f.setUndecorated(true);
+        f.setLocationRelativeTo(null);
         f.setVisible(true);
 
         Point sourcePoint = dragSource.getLocationOnScreen();
@@ -123,6 +110,7 @@
 
         try {
             Robot robot = new Robot();
+            robot.waitForIdle();
             robot.mouseMove(sourcePoint.x, sourcePoint.y);
             Point start = new Point(
                     sourcePoint.x,
@@ -155,112 +143,5 @@
             e.printStackTrace();
             throw new RuntimeException("test failed: drop was not successful with exception " + e);
         }
-    }// start()
+    }
 }// class DnDAcceptanceTest
-
-
-/**
- * *************************************************
- * Standard Test Machinery
- * DO NOT modify anything below -- it's a standard
- * chunk of code whose purpose is to make user
- * interaction uniform, and thereby make it simpler
- * to read and understand someone else's test.
- * **************************************************
- */
-class Sysout {
-    private static TestDialog dialog;
-
-    public static void createDialogWithInstructions(String[] instructions) {
-        dialog = new TestDialog(new Frame(), "Instructions");
-        dialog.printInstructions(instructions);
-        dialog.show();
-        println("Any messages for the tester will display here.");
-    }
-
-    public static void createDialog() {
-        dialog = new TestDialog(new Frame(), "Instructions");
-        String[] defInstr = {"Instructions will appear here. ", ""};
-        dialog.printInstructions(defInstr);
-        dialog.show();
-        println("Any messages for the tester will display here.");
-    }
-
-
-    public static void printInstructions(String[] instructions) {
-        dialog.printInstructions(instructions);
-    }
-
-
-    public static void println(String messageIn) {
-        dialog.displayMessage(messageIn);
-    }
-
-}// Sysout  class
-
-
-class TestDialog extends Dialog {
-
-    TextArea instructionsText;
-    TextArea messageText;
-    int maxStringLength = 80;
-
-    //DO NOT call this directly, go through Sysout
-    public TestDialog(Frame frame, String name) {
-        super(frame, name);
-        int scrollBoth = TextArea.SCROLLBARS_BOTH;
-        instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
-        add("North", instructionsText);
-
-        messageText = new TextArea("", 5, maxStringLength, scrollBoth);
-        add("South", messageText);
-
-        pack();
-
-        show();
-    }// TestDialog()
-
-    //DO NOT call this directly, go through Sysout
-    public void printInstructions(String[] instructions) {
-        //Clear out any current instructions
-        instructionsText.setText("");
-
-        //Go down array of instruction strings
-
-        String printStr, remainingStr;
-        for (int i = 0; i < instructions.length; i++) {
-            //chop up each into pieces maxSringLength long
-            remainingStr = instructions[i];
-            while (remainingStr.length() > 0) {
-                //if longer than max then chop off first max chars to print
-                if (remainingStr.length() >= maxStringLength) {
-                    //Try to chop on a word boundary
-                    int posOfSpace = remainingStr.
-                            lastIndexOf(' ', maxStringLength - 1);
-
-                    if (posOfSpace <= 0) posOfSpace = maxStringLength - 1;
-
-                    printStr = remainingStr.substring(0, posOfSpace + 1);
-                    remainingStr = remainingStr.substring(posOfSpace + 1);
-                }
-                //else just print
-                else {
-                    printStr = remainingStr;
-                    remainingStr = "";
-                }
-
-                instructionsText.append(printStr + "\n");
-
-            }// while
-
-        }// for
-
-    }//printInstructions()
-
-    //DO NOT call this directly, go through Sysout
-    public void displayMessage(String messageIn) {
-        messageText.append(messageIn + "\n");
-    }
-
-}// TestDialog  class
-
--- a/test/jdk/java/awt/dnd/InterJVMGetDropSuccessTest/InterJVMGetDropSuccessTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2014, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4658741
-  @summary verifies that getDropSuccess() returns correct value for inter-JVM DnD
-  @author das@sparc.spb.su area=dnd
-  @run applet InterJVMGetDropSuccessTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>InterJVMGetDropSuccessTest<br>Bug ID: 4658741</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="InterJVMGetDropSuccessTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/dnd/InterJVMGetDropSuccessTest/InterJVMGetDropSuccessTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/dnd/InterJVMGetDropSuccessTest/InterJVMGetDropSuccessTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,53 +22,20 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4658741
   @summary verifies that getDropSuccess() returns correct value for inter-JVM DnD
-  @author das@sparc.spb.su area=dnd
-  @run applet InterJVMGetDropSuccessTest.html
+  @run main InterJVMGetDropSuccessTest
 */
 
-// Note there is no @ in front of test above.  This is so that the
-//  harness will not mistake this file as a test file.  It should
-//  only see the html file as a test file. (the harness runs all
-//  valid test files, so it would run this test twice if this file
-//  were valid as well as the html file.)
-// Also, note the area= after Your Name in the author tag.  Here, you
-//  should put which functional area the test falls in.  See the
-//  AWT-core home page -> test areas and/or -> AWT team  for a list of
-//  areas.
-// Note also the 'InterJVMGetDropSuccessTest.html' in the run tag.  This should
-//  be changed to the name of the test.
-
-
-/**
- * InterJVMGetDropSuccessTest.java
- *
- * summary: verifies that getDropSuccess() returns correct value for inter-JVM DnD
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.datatransfer.*;
 import java.awt.dnd.*;
 import java.awt.event.*;
 import java.io.*;
-import javax.swing.*;
 
-
-//Automated tests should run as applet tests if possible because they
-// get their environments cleaned up, including AWT threads, any
-// test created threads, and any system resources used by the test
-// such as file descriptors.  (This is normally not a problem as
-// main tests usually run in a separate VM, however on some platforms
-// such as the Mac, separate VMs are not possible and non-applet
-// tests will cause problems).  Also, you don't have to worry about
-// synchronisation stuff in Applet tests they way you do in main
-// tests...
-
-
-public class InterJVMGetDropSuccessTest extends Applet {
+public class InterJVMGetDropSuccessTest {
 
     private int returnCode = Util.CODE_NOT_RETURNED;
     private boolean successCodes[] = { true, false };
@@ -85,6 +52,12 @@
         };
     final DropTarget dropTarget = new DropTarget(frame, dropTargetListener);
 
+    public static void main(final String[] args) {
+        InterJVMGetDropSuccessTest app = new InterJVMGetDropSuccessTest();
+        app.init();
+        app.start();
+    }
+
     public void init() {
         frame.setTitle("Test frame");
         frame.setBounds(100, 100, 150, 150);
--- a/test/jdk/java/awt/dnd/NoFormatsCrashTest/NoFormatsCrashTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-<!--
- Copyright (c) 2014, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4870762
-  @summary tests that a drop target JVM doesn't crash if the source doesn't export 
-           data in native formats.
-  @author das@sparc.spb.su area=dnd
-  @run applet NoFormatsCrashTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>NoFormatsCrashTest<br>Bug ID: 4870762</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="NoFormatsCrashTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/dnd/NoFormatsCrashTest/NoFormatsCrashTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/dnd/NoFormatsCrashTest/NoFormatsCrashTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,55 +22,21 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4870762
   @summary tests that a drop target JVM doesn't crash if the source doesn't export
            data in native formats.
-  @author das@sparc.spb.su area=dnd
-  @compile NoFormatsCrashTest.java
-  @run applet NoFormatsCrashTest.html
+  @run main NoFormatsCrashTest main
 */
 
-// Note there is no @ in front of test above.  This is so that the
-//  harness will not mistake this file as a test file.  It should
-//  only see the html file as a test file. (the harness runs all
-//  valid test files, so it would run this test twice if this file
-//  were valid as well as the html file.)
-// Also, note the area= after Your Name in the author tag.  Here, you
-//  should put which functional area the test falls in.  See the
-//  AWT-core home page -> test areas and/or -> AWT team  for a list of
-//  areas.
-// Note also the 'NoFormatsCrashTest.html' in the run tag.  This should
-//  be changed to the name of the test.
-
-
-/**
- * NoFormatsCrashTest.java
- *
- * summary: tests that a drop target JVM doesn't crash if the source doesn't export
- *          data in native formats.
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.datatransfer.*;
 import java.awt.dnd.*;
 import java.awt.event.*;
 import java.io.*;
 
-
-//Automated tests should run as applet tests if possible because they
-// get their environments cleaned up, including AWT threads, any
-// test created threads, and any system resources used by the test
-// such as file descriptors.  (This is normally not a problem as
-// main tests usually run in a separate VM, however on some platforms
-// such as the Mac, separate VMs are not possible and non-applet
-// tests will cause problems).  Also, you don't have to worry about
-// synchronisation stuff in Applet tests they way you do in main
-// tests...
-
-
-public class NoFormatsCrashTest extends Applet {
+public class NoFormatsCrashTest {
 
     final Frame frame = new Frame();
     private volatile Process process;
@@ -78,6 +44,13 @@
     static final int FRAME_ACTIVATION_TIMEOUT = 2000;
 
     public static void main(String[] args) {
+        if (args.length > 0 && args[0].equals("main")) {
+            NoFormatsCrashTest test = new NoFormatsCrashTest();
+            test.init();
+            test.start();
+            return;
+        }
+
         NoFormatsCrashTest test = new NoFormatsCrashTest();
         test.run(args);
     }
--- a/test/jdk/java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<!--
- Copyright (c) 2009, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4899516
-  @summary Transferable has no DataFlavors when dragging from Gnome window to Swing
-  @author : area=dnd
-  @library ../../regtesthelpers
-  @library ../../regtesthelpers/process
-  @build Util
-  @build ProcessResults ProcessCommunicator 
-  @run applet/othervm URIListBetweenJVMsTest.html
-
--->
-<head>
-<title> DnD of URI-List across JVM </title>
-</head>
-<body>
-
-<h1>URIListBetweenJVMsTest<br>Bug ID: 4899516</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="URIListBetweenJVMsTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/dnd/URIListBetweenJVMsTest/URIListBetweenJVMsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 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
@@ -22,39 +22,30 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4899516
   @summary Transferable has no DataFlavors when dragging from Gnome window to Swing
-  @author : area=dnd
-  @run applet URIListBetweenJVMsTest.html
+  @library ../../regtesthelpers
+  @library ../../regtesthelpers/process
+  @build Util
+  @build ProcessResults ProcessCommunicator
+  @run main/othervm URIListBetweenJVMsTest main
 */
 
-/**
- * URIListBetweenJVMsTest.java
- *
- * summary: Transferable has no DataFlavors when dragging from Gnome window to Swing
- */
-
 import static java.lang.Thread.sleep;
 
 import test.java.awt.regtesthelpers.process.ProcessCommunicator;
 import test.java.awt.regtesthelpers.process.ProcessResults;
 import test.java.awt.regtesthelpers.Util;
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.InputEvent;
-import java.io.*;
 
-public class URIListBetweenJVMsTest extends Applet {
+public class URIListBetweenJVMsTest {
 
     // information related to the test in common
     static int VISIBLE_RAWS_IN_LIST=15;
 
-    public void init() {
-        setLayout(new BorderLayout());
-
-    }//End  init()
-
     public void start() {
 
     String toolkit = Toolkit.getDefaultToolkit().getClass().getName();
@@ -140,6 +131,10 @@
     }
 
     public static void main (String [] args) {
+        if (args.length > 0 && args[0].equals("main")) {
+            new URIListBetweenJVMsTest().start();
+            return;
+        }
         Point dragSourcePoint = new Point(InterprocessArguments.DRAG_SOURCE_POINT_X_ARGUMENT.extract(args),
                 InterprocessArguments.DRAG_SOURCE_POINT_Y_ARGUMENT.extract(args));
         Point targetFrameLocation = new Point(InterprocessArguments.TARGET_FRAME_X_POSITION_ARGUMENT.extract(args),
--- a/test/jdk/java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-<!--
- Copyright (c) 2013, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 8029565
-  @summary Conversion of a URI list to File list fails
-  @author Petr Pchelko <petr.pchelko@oracle.com>
-  @library ../../regtesthelpers
-  @library ../../regtesthelpers/process
-  @build Util
-  @build ProcessResults ProcessCommunicator
-  @run applet/othervm URIListToFileListBetweenJVMsTest.html
-
--->
-<head>
-<title> DnD of File-List across JVM </title>
-</head>
-<body>
-
-<h1>URIListToFileListBetweenJVMsTest<br>Bug ID: 5079469</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="URIListToFileListBetweenJVMsTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/dnd/URIListToFileListBetweenJVMsTest/URIListToFileListBetweenJVMsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,42 +22,31 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 8029565
   @summary Conversion of a URI list to File list fails
-  @author Petr Pchelko <petr.pchelko@oracle.com>
   @library ../../regtesthelpers
   @library ../../regtesthelpers/process
   @build Util
   @build ProcessResults ProcessCommunicator
-  @run applet/othervm URIListToFileListBetweenJVMsTest.html
- */
-
-/**
- * URIListToFileListBetweenJVMsTest.java
- *
- * summary: DnD of File-List across JVM adds two empty items to the list
+  @run main/othervm URIListToFileListBetweenJVMsTest main
  */
 
 import test.java.awt.regtesthelpers.Util;
 import test.java.awt.regtesthelpers.process.ProcessCommunicator;
 import test.java.awt.regtesthelpers.process.ProcessResults;
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.InputEvent;
 
 import static java.lang.Thread.sleep;
 
-public class URIListToFileListBetweenJVMsTest extends Applet {
+public class URIListToFileListBetweenJVMsTest {
 
     // information related to the test in common
     static int VISIBLE_RAWS_IN_LIST=15;
 
-    public void init() {
-        setLayout(new BorderLayout());
-    }
-
     public void start() {
 
         SourceFileListFrame sourceFrame = new SourceFileListFrame();
@@ -127,7 +116,11 @@
         }
     }
 
-    public static void main (String [] args) throws Exception {
+    public static void main(final String [] args) throws Exception {
+        if (args.length > 0 && args[0].equals("main")) {
+            new URIListToFileListBetweenJVMsTest().start();
+            return;
+        }
         Point dragSourcePoint = new Point(InterprocessArguments.DRAG_SOURCE_POINT_X_ARGUMENT.extract(args),
                 InterprocessArguments.DRAG_SOURCE_POINT_Y_ARGUMENT.extract(args));
         Point targetFrameLocation = new Point(InterprocessArguments.TARGET_FRAME_X_POSITION_ARGUMENT.extract(args),
--- a/test/jdk/java/awt/event/ComponentEvent/MovedResizedTardyEventTest/MovedResizedTardyEventTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<!--
- Copyright (c) 2004, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug          4985250
-  @summary      COMPONENT_MOVED/RESIZED tardy events shouldn't be generated.
-  @author       tav@sparc.spb.su
-  @modules java.desktop/sun.awt
-  @run applet MovedResizedTardyEventTest.html
-  -->
-<head>
-<title>MovedResizedTardyEventTest</title>
-</head>
-<body>
-
-<h1>MovedResizedTardyEventTest<br>Bug ID: 4985250</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="MovedResizedTardyEventTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/event/ComponentEvent/MovedResizedTardyEventTest/MovedResizedTardyEventTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/ComponentEvent/MovedResizedTardyEventTest/MovedResizedTardyEventTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,26 +22,26 @@
  */
 
 /*
-  test
-  @bug      4985250
-  @summary  COMPONENT_MOVED/RESIZED tardy events shouldn't be generated.
-  @author   tav@sparc.spb.su
-  @run applet MovedResizedTardyEventTest.html
+  @test
+  @key headful
+  @bug          4985250
+  @summary      COMPONENT_MOVED/RESIZED tardy events shouldn't be generated.
+  @modules java.desktop/sun.awt
+  @run main MovedResizedTardyEventTest
 */
 
 import java.awt.*;
 import java.awt.event.*;
-import java.applet.Applet;
 import java.lang.reflect.InvocationTargetException;
 
-public class MovedResizedTardyEventTest extends Applet {
+public class MovedResizedTardyEventTest {
     Frame f1 = new Frame("F-1");
     Frame f2 = new Frame("F-2");
 
     boolean eventFlag = false;
 
     public static void main(String[] args) {
-        Applet a = new MovedResizedTardyEventTest();
+        MovedResizedTardyEventTest a = new MovedResizedTardyEventTest();
         a.start();
     }
 
--- a/test/jdk/java/awt/event/KeyEvent/KeyTyped/CtrlASCII.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2007, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug  6497426
-  @summary ests that pressing of Ctrl+ascii mostly fires KEY_TYPED with a Unicode control symbols
-  @author yuri.nesterenko@... area=awt.keyboard
-  @run applet CtrlASCII.html
-  -->
-<head>
-<title> CtrlASCII </title>
-</head>
-<body>
-
-<h1>CtrlASCII<br>Bug ID: 6497426</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="CtrlASCII.class" WIDTH=400 HEIGHT=300></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/event/KeyEvent/KeyTyped/CtrlASCII.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/KeyEvent/KeyTyped/CtrlASCII.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,38 +22,17 @@
  */
 
 /*
- * test
- * @bug 6497426
- * @summary Tests that pressing of Ctrl+ascii mostly fires KEY_TYPED with a Unicode control symbols
- * @author Yuri.Nesterenko@... area=awt.keyboard
- * @run applet CtrlASCII.html
+  @test
+  @key headful
+  @bug  6497426
+  @summary ests that pressing of Ctrl+ascii mostly fires KEY_TYPED with a Unicode control symbols
+  @run main CtrlASCII
  */
 
-// Note there is no @ in front of test above.  This is so that the
-//  harness will not mistake this file as a test file.  It should
-//  only see the html file as a test file. (the harness runs all
-//  valid test files, so it would run this test twice if this file
-//  were valid as well as the html file.)
-// Also, note the area= after Your Name in the author tag.  Here, you
-//  should put which functional area the test falls in.  See the
-//  AWT-core home page -> test areas and/or -> AWT team  for a list of
-//  areas.
-// Note also the 'RobotLWTest.html' in the run tag.  This should
-//  be changed to the name of the test.
-
-
-/**
- * CtrlASCII.java
- *
- * @summary Tests that pressing of Ctrl+ascii mostly fires KEY_TYPED with a Unicode control symbols
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import java.util.*;
 
-
 //
 // In this test, a key listener for KEY_TYPED checks if a character typed has
 // a correspondent keycode in an initially filled hashtable.
@@ -63,8 +42,7 @@
 // produce a unicode character, so there will be no KEY_TYPED and no problem.
 // Test doesn't try to verify Ctrl+deadkey behavior.
 //
-
-public class CtrlASCII extends Applet implements KeyListener
+public class CtrlASCII extends Frame implements KeyListener
 {
     // Declare things used in the test, like buttons and labels here
     static Hashtable<Character, Integer> keycharHash = new Hashtable<Character, Integer>();
@@ -194,6 +172,7 @@
     public void start ()
     {
         setSize(400,300);
+        setLocationRelativeTo(null);
         setVisible(true);
 
         String original = "0123456789";
--- a/test/jdk/java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsoluteCoordsTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2004, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4992908
-  @summary Need way to get location of MouseEvent in screen  coordinates (Unit-test)
-  @author Andrei.Dmitriev area=event
-  @library ../../../regtesthelpers
-  @build Util
-  @run applet FrameMouseEventAbsoluteCoordsTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>FrameMouseEventAbsoluteCoordsTest<br>Bug ID: 4992908 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="FrameMouseEventAbsoluteCoordsTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsoluteCoordsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsoluteCoordsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -22,14 +22,15 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4992908
   @summary Need way to get location of MouseEvent in screen  coordinates (Unit-test)
-  @author Andrei.Dmitriev area=event
-  @run applet FrameMouseEventAbsoluteCoordsTest.html
+  @library ../../../regtesthelpers
+  @build Util
+  @run main FrameMouseEventAbsoluteCoordsTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import test.java.awt.regtesthelpers.Util;
@@ -39,7 +40,7 @@
 // Click on this frame.
 // verify that our MouseEvent contain correct xAbs, yAbs values
 
-public class FrameMouseEventAbsoluteCoordsTest extends Applet implements MouseListener
+public class FrameMouseEventAbsoluteCoordsTest implements MouseListener
 {
     Robot robot;
     Frame frame = new Frame("MouseEvent Test Frame II");
@@ -47,20 +48,23 @@
     Point mousePositionAbsolute;
     Point mousePosition;
 
+    public static void main(final String[] args) {
+        FrameMouseEventAbsoluteCoordsTest app = new FrameMouseEventAbsoluteCoordsTest();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
-
-        this.setLayout (new BorderLayout ());
         button.addMouseListener(this);
         frame.add(button);
         frame.pack();
+        frame.setLocationRelativeTo(null);
     }//End  init()
 
     public void start ()
     {
-        setSize (200,200);
         frame.setVisible(true);
-        validate();
         Util.waitForIdle(robot);
 
         try {
--- a/test/jdk/java/awt/event/MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2004, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4992908
-  @summary Need way to get location of MouseEvent in screen coordinates
-  @author Andrei.Dmitriev area=event
-  @library ../../../regtesthelpers
-  @build Util
-  @run applet MenuDragMouseEventAbsoluteCoordsTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>MenuDragMouseEventAbsoluteCoordsTest<br>Bug ID: 4992908 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="MenuDragMouseEventAbsoluteCoordsTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/event/MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/MouseEvent/MenuDragMouseEventAbsoluteCoordsTest/MenuDragMouseEventAbsoluteCoordsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,19 +22,18 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4992908
   @summary Need way to get location of MouseEvent in screen coordinates
-  @author Andrei.Dmitriev area=event
-  @run applet MenuDragMouseEventAbsoluteCoordsTest.html
+  @library ../../../regtesthelpers
+  @build Util
+  @run main MenuDragMouseEventAbsoluteCoordsTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import javax.swing.event.*;
 import java.awt.event.*;
-import javax.swing.MenuSelectionManager;
-import javax.swing.MenuElement;
 import test.java.awt.regtesthelpers.Util;
 
 // The test consits of several parts:
@@ -44,12 +43,19 @@
 // getLocationOnScreen(),  get(X|Y), getPoint() .
 
 
-public class MenuDragMouseEventAbsoluteCoordsTest extends Applet implements MouseListener
+public class MenuDragMouseEventAbsoluteCoordsTest implements MouseListener
 {
     Frame frame = new Frame("MenuDragMouseEvent Test Frame");
 
     Point mousePositionOnScreen = new Point(200, 200);
     Point mousePosition = new Point(100, 100);
+
+    public static void main(String[] args) {
+        MenuDragMouseEventAbsoluteCoordsTest app = new MenuDragMouseEventAbsoluteCoordsTest();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
         frame.addMouseListener(this);
@@ -60,7 +66,6 @@
         //Get things going.  Request focus, set size, et cetera
         frame.setSize (200,200);
         frame.setVisible(true);
-        validate();
 
         try {
             Util.waitForIdle(new Robot());
--- a/test/jdk/java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2007, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6267983
-  @summary PIT: MouseClicked is triggered when the mouse is released outside the tray icon, Win32
-  @author dmitry.cherepanov@... area=awt.event
-  @library    ../../../regtesthelpers
-  @build      Util
-  @run applet MouseClickTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>MouseClickTest<br>Bug ID: 6267983</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="MouseClickTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/MouseEvent/MouseClickTest/MouseClickTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,42 +22,33 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6267983
   @summary PIT: MouseClicked is triggered when the mouse is released outside the tray icon, Win32
-  @author dmitry.cherepanov@... area=awt.event
-  @run applet MouseClickTest.html
+  @library    ../../../regtesthelpers
+  @build      Util
+  @run main MouseClickTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import test.java.awt.regtesthelpers.Util;
 
-public class MouseClickTest extends Applet
+public class MouseClickTest
 {
     private static final int TIMEOUT = 3000;
 
-    public void init()
-    {
-        setLayout (new BorderLayout ());
-    }
-
     public void start ()
     {
-        setSize (200,200);
-        setVisible(true);
-        validate();
-
         runTests();
     }
 
     public static final void main(String args[])
     {
         MouseClickTest test = new MouseClickTest();
-        test.init();
         test.start();
     }
 
--- a/test/jdk/java/awt/event/MouseEvent/MouseWheelEventAbsoluteCoordsTest/MouseWheelEventAbsoluteCoordsTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2004, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4992908
-  @summary Need way to get location of MouseEvent in screen coordinates
-  @author Andrei.Dmitriev area=event 
-  @library ../../../regtesthelpers
-  @build Util
-  @run applet MouseWheelEventAbsoluteCoordsTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>MouseWheelEventAbsoluteCoordsTest<br>Bug ID: 4992908  </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="MouseWheelEventAbsoluteCoordsTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/event/MouseEvent/MouseWheelEventAbsoluteCoordsTest/MouseWheelEventAbsoluteCoordsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/MouseEvent/MouseWheelEventAbsoluteCoordsTest/MouseWheelEventAbsoluteCoordsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -22,14 +22,15 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4992908
   @summary Need way to get location of MouseEvent in screen coordinates
-  @author Andrei.Dmitriev area=event
-  @run applet MouseWheelEventAbsoluteCoordsTest.html
+  @library ../../../regtesthelpers
+  @build Util
+  @run main MouseWheelEventAbsoluteCoordsTest
 */
 
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import test.java.awt.regtesthelpers.Util;
@@ -41,17 +42,21 @@
 // getLocationOnScreen(),  get(X|Y), getPoint() .
 
 
-public class MouseWheelEventAbsoluteCoordsTest extends Applet implements MouseWheelListener
+public class MouseWheelEventAbsoluteCoordsTest implements MouseWheelListener
 {
     Frame frame = new Frame("MouseWheelEvent Test Frame");
 
     Point mousePositionOnScreen = new Point(200, 200);
     Point mousePosition = new Point(100, 100);
+
+    public static void main(final String[] args) {
+        MouseWheelEventAbsoluteCoordsTest app = new MouseWheelEventAbsoluteCoordsTest();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
-
-        this.setLayout (new BorderLayout ());
-
         frame.addMouseWheelListener(this);
     }//End  init()
 
@@ -62,7 +67,6 @@
         frame.setLocation(47, 47);
 
         frame.setVisible(true);
-        validate();
         try {
             Util.waitForIdle(new Robot());
         }catch (Exception e){
--- a/test/jdk/java/awt/event/MouseEvent/RobotLWTest/RobotLWTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2000, 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.
--->
-
-<html>
-<!--
-  @test
-  @key headful
-  @bug 4350402
-  @summary Tests that mouse behavior on LW component
-  @compile ../../../regtesthelpers/Util.java
-  @run applet RobotLWTest.html
-  -->
-<head>
-<title> RobotLWTest </title>
-</head>
-<body>
-
-<h1>RobotLWTest<br>Bug ID: 4058400</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="RobotLWTest.class" WIDTH=350 HEIGHT=100></APPLET>
-</body>
-</html>
--- a/test/jdk/java/awt/event/MouseEvent/RobotLWTest/RobotLWTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/MouseEvent/RobotLWTest/RobotLWTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -22,29 +22,24 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 4350402
   @summary Tests that mouse behavior on LW component
+  @compile ../../../regtesthelpers/Util.java
+  @run main RobotLWTest
 */
 
-/**
- * RobotLWTest.java
- *
- * summary:
- */
-
-import java.applet.Applet;
 import java.awt.*;
 import java.awt.event.*;
 import test.java.awt.regtesthelpers.Util;
 
-public class RobotLWTest extends Applet
-{
-    //Declare things used in the test, like buttons and labels here
+public class RobotLWTest {
 
-    public void init()
-    {
-    }//End  init()
+    public static void main(String[] args) {
+        RobotLWTest app = new RobotLWTest();
+        app.start();
+    }
 
     public void start ()
     {
@@ -54,6 +49,7 @@
         c.add(b);
         frame.add(c);
         frame.setSize(400,400);
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
 
         try {
--- a/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_2.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2007, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6480024
-  @library ../../../regtesthelpers
-  @build Util Sysout AbstractTest
-  @summary stack overflow on mouse wheel rotation within JApplet
-  @author Andrei Dmitriev: area=awt.event
-  @run applet InfiniteRecursion_2.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>InfiniteRecursion_2<br>Bug ID: 6480024 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="InfiniteRecursion_2.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_2.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_2.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -22,13 +22,13 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6480024
   @library ../../../regtesthelpers
   @build Util Sysout AbstractTest
-  @summary stack overflow on mouse wheel rotation within Applet
-  @author Andrei Dmitriev: area=awt.event
-  @run applet InfiniteRecursion_2.html
+  @summary stack overflow on mouse wheel rotation within JApplet
+  @run main InfiniteRecursion_2
 */
 
 /**
@@ -49,11 +49,8 @@
 import javax.swing.*;
 import test.java.awt.regtesthelpers.Util;
 import test.java.awt.regtesthelpers.AbstractTest;
-import test.java.awt.regtesthelpers.Sysout;
 
-import java.applet.Applet;
-
-public class InfiniteRecursion_2 extends Applet {
+public class InfiniteRecursion_2 extends Frame {
     final static Robot robot = Util.createRobot();
     final static int MOVE_COUNT = 5;
     //*2 for both rotation directions,
@@ -61,6 +58,12 @@
     final static int EXPECTED_COUNT = MOVE_COUNT * 2 * 2;
     static int actualEvents = 0;
 
+    public static void main(final String[] args) {
+        InfiniteRecursion_2 app = new InfiniteRecursion_2();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
         setLayout (new BorderLayout ());
@@ -72,6 +75,7 @@
         JButton jButton = new JButton();
 
         this.setSize(200, 200);
+        this.setLocationRelativeTo(null);
         this.addMouseWheelListener(new MouseWheelListener() {
                 public void mouseWheelMoved(MouseWheelEvent e)
                 {
--- a/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_3.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!--
- Copyright (c) 2007, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 6480024
-  @library ../../../regtesthelpers
-  @build Util Sysout AbstractTest
-  @summary stack overflow on mouse wheel rotation within JApplet
-  @author Andrei Dmitriev: area=awt.event
-  @run applet InfiniteRecursion_3.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>InfiniteRecursion_3<br>Bug ID: 6480024 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="InfiniteRecursion_3.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
-
--- a/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_3.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/awt/event/MouseWheelEvent/InfiniteRecursion/InfiniteRecursion_3.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -22,13 +22,13 @@
  */
 
 /*
-  test
+  @test
+  @key headful
   @bug 6480024
   @library ../../../regtesthelpers
   @build Util Sysout AbstractTest
-  @summary stack overflow on mouse wheel rotation within Applet
-  @author Andrei Dmitriev: area=awt.event
-  @run applet InfiniteRecursion_3.html
+  @summary stack overflow on mouse wheel rotation within JApplet
+  @run main InfiniteRecursion_3
 */
 
 /**
@@ -44,10 +44,8 @@
 import javax.swing.*;
 import test.java.awt.regtesthelpers.Util;
 import test.java.awt.regtesthelpers.AbstractTest;
-import test.java.awt.regtesthelpers.Sysout;
-import java.applet.Applet;
 
-public class InfiniteRecursion_3 extends Applet {
+public class InfiniteRecursion_3 extends Frame {
     final static Robot robot = Util.createRobot();
     final static int MOVE_COUNT = 5;
     //*2 for both rotation directions,
@@ -55,6 +53,12 @@
     final static int EXPECTED_COUNT = MOVE_COUNT * 2 * 2;
     static int actualEvents = 0;
 
+    public static void main(final String[] args) {
+        InfiniteRecursion_3 app = new InfiniteRecursion_3();
+        app.init();
+        app.start();
+    }
+
     public void init()
     {
         setLayout (new BorderLayout ());
@@ -74,7 +78,7 @@
             });
 
         this.add(jButton);
-
+        this.setLocationRelativeTo(null);
         this.setVisible(true);
         this.validate();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/Process/WaitFor.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8220684
+ * @summary Process.waitFor(long, TimeUnit) can return false for a process
+ *          that exited within the timeout
+ * @run main/othervm WaitFor
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.TimeUnit;
+
+public class WaitFor {
+    public static void main(String[] args) throws Throwable {
+        int failCnt = 0;
+        for (int i = 0; i < 30; ++i) {
+            Process proc = new MyProcess(new ProcessBuilder("true").start());
+            boolean exited = proc.waitFor(100, TimeUnit.MILLISECONDS);
+            if (!exited && !proc.isAlive()) failCnt++;
+        }
+        if (failCnt > 10) {
+            throw new RuntimeException(failCnt + " processes were still alive"
+                + " after timeout");
+        }
+    }
+}
+
+/**
+ * This class uses the default implementation of java.lang.Process#waitFor(long,
+ * TimeUnit), and delegates all other calls to the actual implementation of
+ * Process.
+ */
+class MyProcess extends Process {
+    Process impl;
+    public MyProcess(Process impl) { this.impl = impl; }
+    public OutputStream getOutputStream() { return impl.getOutputStream(); }
+    public InputStream getInputStream() { return impl.getInputStream(); }
+    public InputStream getErrorStream() { return impl.getErrorStream(); }
+    public int waitFor() throws InterruptedException { return impl.waitFor(); }
+    public int exitValue() { return impl.exitValue(); }
+    public void destroy() { impl.destroy(); }
+    public ProcessHandle toHandle() { return impl.toHandle(); }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/ThreadGroup/Destroy.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary enumerate(list,n,recurse) may return 0 if the group is being destroyed,
+ *          whereas it should never return a value < n. This lead to inconsistent
+ *          results if ThreadGroup::enumerate is called concurrently at the same
+ *          time that a child group is being destroyed. This is a race condition,
+ *          and this test will not always fail without the fix, but it does fail
+ *          often enough.
+ * @bug 8219197
+ *
+ */
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Destroy {
+
+    static final class Task implements Runnable {
+        final Semaphore sem;
+        final CountDownLatch count;
+
+        public Task(Semaphore sem, CountDownLatch count) {
+            this.sem = sem;
+            this.count = count;
+        }
+
+        @Override
+        public void run() {
+            try {
+                count.countDown();
+                sem.acquire();
+            } catch (Throwable t) {
+                t.printStackTrace();
+            } finally {
+                System.out.println(Thread.currentThread().getName()
+                        + " exiting");
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        testDestroyChild();
+    }
+
+    public static void testDestroyChild() throws Exception {
+        ThreadGroup root = new ThreadGroup("root");
+        ThreadGroup parent = new ThreadGroup(root,"parent");
+        ThreadGroup child1 = new ThreadGroup(parent, "child1");
+        CountDownLatch count = new CountDownLatch(2);
+        Semaphore sem1 = new Semaphore(1);
+        Semaphore sem2 = new Semaphore(1);
+        Thread t1 = new Thread(parent, new Task(sem1, count), "PT1");
+        Thread t2 = new Thread(parent, new Task(sem2, count), "PT2");
+        sem1.acquire();
+        sem2.acquire();
+        try {
+
+            t1.start();
+            t2.start();
+
+            System.out.println("\nAwaiting parent threads...");
+            count.await();
+            Thread[] threads = new Thread[2];
+            int nb = root.enumerate(threads, true);
+            if (nb != 2) {
+                throw new AssertionError("wrong number of threads: " + nb);
+            }
+
+            Thread t3 = new Thread(child1::destroy, "destroy");
+            AtomicInteger nbr = new AtomicInteger();
+            Thread t4 = new Thread("enumerate") {
+                public void run() {
+                    Thread[] threads = new Thread[42];
+                    nbr.addAndGet(root.enumerate(threads, true));
+                }
+            };
+            t4.start();
+            t3.start();
+            t4.join();
+            t3.join();
+            if (nbr.get() != nb) {
+                throw new AssertionError("wrong number of threads: " + nbr.get());
+            }
+
+        } finally {
+            sem1.release();
+            sem2.release();
+        }
+        t1.join();
+        t2.join();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/AsyncShutdown.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @requires (os.family == "linux" | os.family == "mac")
+ * @run testng AsyncShutdown
+ * @summary Test shutdownInput/shutdownOutput with threads blocked in read/write
+ */
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class AsyncShutdown {
+
+    public void testShutdownInput1() throws IOException {
+        withConnection((s1, s2) -> {
+            scheduleShutdownInput(s1, 2000);
+            int n = s1.getInputStream().read();
+            assertTrue(n == -1);
+        });
+    }
+
+    public void testShutdownInput2() throws IOException {
+        withConnection((s1, s2) -> {
+            scheduleShutdownInput(s1, 2000);
+            s1.setSoTimeout(30*1000);
+            int n = s1.getInputStream().read();
+            assertTrue(n == -1);
+        });
+    }
+
+    public void testShutdownOutput1() throws IOException {
+        withConnection((s1, s2) -> {
+            scheduleShutdownOutput(s1, 2000);
+            byte[] data = new byte[128*1024];
+            try {
+                while (true) {
+                    s1.getOutputStream().write(data);
+                }
+            } catch (IOException expected) { }
+        });
+    }
+
+    public void testShutdownOutput2() throws IOException {
+        withConnection((s1, s2) -> {
+            s1.setSoTimeout(100);
+            try {
+                s1.getInputStream().read();
+                assertTrue(false);
+            } catch (SocketTimeoutException e) { }
+
+            scheduleShutdownOutput(s1, 2000);
+            byte[] data = new byte[128*1024];
+            try {
+                while (true) {
+                    s1.getOutputStream().write(data);
+                }
+            } catch (IOException expected) { }
+        });
+    }
+
+    static void scheduleShutdownInput(Socket s, long delay) {
+        schedule(() -> {
+            try {
+                s.shutdownInput();
+            } catch (IOException ioe) { }
+        }, delay);
+    }
+
+    static void scheduleShutdownOutput(Socket s, long delay) {
+        schedule(() -> {
+            try {
+                s.shutdownOutput();
+            } catch (IOException ioe) { }
+        }, delay);
+    }
+
+    static void schedule(Runnable task, long delay) {
+        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+        try {
+            executor.schedule(task, delay, TimeUnit.MILLISECONDS);
+        } finally {
+            executor.shutdown();
+        }
+    }
+
+    interface ThrowingBiConsumer<T, U> {
+        void accept(T t, U u) throws IOException;
+    }
+
+    static void withConnection(ThrowingBiConsumer<Socket, Socket> consumer)
+        throws IOException
+    {
+        Socket s1 = null;
+        Socket s2 = null;
+        try (ServerSocket ss = new ServerSocket(0)) {
+            s1 = new Socket();
+            s1.connect(ss.getLocalSocketAddress());
+            s2 = ss.accept();
+            consumer.accept(s1, s2);
+        } finally {
+            if (s1 != null) s1.close();
+            if (s2 != null) s2.close();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/ConnectionReset.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @requires os.family != "solaris"
+ * @run testng ConnectionReset
+ * @summary Test behavior of read and available when a connection is reset
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ConnectionReset {
+
+    static final int REPEAT_COUNT = 5;
+
+    /**
+     * Tests available before read when there are no bytes to read
+     */
+    public void testAvailableBeforeRead1() throws IOException {
+        System.out.println("testAvailableBeforeRead1");
+        withResetConnection(null, s -> {
+            InputStream in = s.getInputStream();
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(bytesAvailable == 0);
+                try {
+                    int bytesRead = in.read();
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                    } else {
+                        System.out.println("read => 1 byte");
+                    }
+                    assertTrue(false);
+                } catch (IOException ioe) {
+                    System.out.format("read => %s (expected)%n", ioe);
+                }
+            }
+        });
+    }
+
+    /**
+     * Tests available before read when there are bytes to read
+     */
+    public void testAvailableBeforeRead2() throws IOException {
+        System.out.println("testAvailableBeforeRead2");
+        byte[] data = { 1, 2, 3 };
+        withResetConnection(data, s -> {
+            InputStream in = s.getInputStream();
+            int remaining = data.length;
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(bytesAvailable <= remaining);
+                try {
+                    int bytesRead = in.read();
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                        assertTrue(false);
+                    } else {
+                        System.out.println("read => 1 byte");
+                        assertTrue(remaining > 0);
+                        remaining--;
+                    }
+                } catch (IOException ioe) {
+                    System.out.format("read => %s%n", ioe);
+                    remaining = 0;
+                }
+            }
+        });
+    }
+
+    /**
+     * Tests read before available when there are no bytes to read
+     */
+    public void testReadBeforeAvailable1() throws IOException {
+        System.out.println("testReadBeforeAvailable1");
+        withResetConnection(null, s -> {
+            InputStream in = s.getInputStream();
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                try {
+                    int bytesRead = in.read();
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                    } else {
+                        System.out.println("read => 1 byte");
+                    }
+                    assertTrue(false);
+                } catch (IOException ioe) {
+                    System.out.format("read => %s (expected)%n", ioe);
+                }
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(bytesAvailable == 0);
+            }
+        });
+    }
+
+    /**
+     * Tests read before available when there are bytes to read
+     */
+    public void testReadBeforeAvailable2() throws IOException {
+        System.out.println("testReadBeforeAvailable2");
+        byte[] data = { 1, 2, 3 };
+        withResetConnection(data, s -> {
+            InputStream in = s.getInputStream();
+            int remaining = data.length;
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                try {
+                    int bytesRead = in.read();
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                        assertTrue(false);
+                    } else {
+                        System.out.println("read => 1 byte");
+                        assertTrue(remaining > 0);
+                        remaining--;
+                    }
+                } catch (IOException ioe) {
+                    System.out.format("read => %s%n", ioe);
+                    remaining = 0;
+                }
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(bytesAvailable <= remaining);
+            }
+        });
+    }
+
+    /**
+     * Tests available and read on a socket closed after connection reset
+     */
+    public void testAfterClose() throws IOException {
+        System.out.println("testAfterClose");
+        withResetConnection(null, s -> {
+            InputStream in = s.getInputStream();
+            try {
+                in.read();
+                assertTrue(false);
+            } catch (IOException ioe) {
+                // expected
+            }
+            s.close();
+            try {
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(false);
+            } catch (IOException ioe) {
+                System.out.format("available => %s (expected)%n", ioe);
+            }
+            try {
+                int n = in.read();
+                System.out.format("read => %d%n", n);
+                assertTrue(false);
+            } catch (IOException ioe) {
+                System.out.format("read => %s (expected)%n", ioe);
+            }
+        });
+    }
+
+    interface ThrowingConsumer<T> {
+        void accept(T t) throws IOException;
+    }
+
+    /**
+     * Invokes a consumer with a Socket connected to a peer that has closed the
+     * connection with a "connection reset". The peer sends the given data bytes
+     * before closing (when data is not null).
+     */
+    static void withResetConnection(byte[] data, ThrowingConsumer<Socket> consumer)
+        throws IOException
+    {
+        var loopback = InetAddress.getLoopbackAddress();
+        try (var listener = new ServerSocket()) {
+            listener.bind(new InetSocketAddress(loopback, 0));
+            try (var socket = new Socket()) {
+                socket.connect(listener.getLocalSocketAddress());
+                try (Socket peer = listener.accept()) {
+                    if (data != null) {
+                        peer.getOutputStream().write(data);
+                    }
+                    peer.setSoLinger(true, 0);
+                }
+                consumer.accept(socket);
+            }
+        }
+    }
+}
--- a/test/jdk/java/net/Socket/HttpProxy.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/net/Socket/HttpProxy.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,12 @@
 
 /*
  * @test
- * @bug 6370908
+ * @bug 6370908 8220663
  * @summary Add support for HTTP_CONNECT proxy in Socket class
  * @modules java.base/sun.net.www
  * @run main HttpProxy
  * @run main/othervm -Djava.net.preferIPv4Stack=true HttpProxy
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true HttpProxy
  */
 
 import java.io.IOException;
@@ -40,6 +41,9 @@
 import java.net.Proxy;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.List;
 import sun.net.www.MessageHeader;
 
 public class HttpProxy {
@@ -50,9 +54,10 @@
     public static void main(String[] args) throws Exception {
         String host;
         int port;
+        ConnectProxyTunnelServer proxy = null;
         if (args.length == 0) {
             // Start internal proxy
-            ConnectProxyTunnelServer proxy = new ConnectProxyTunnelServer();
+            proxy = new ConnectProxyTunnelServer();
             proxy.start();
             host = "localhost";
             port = proxy.getLocalPort();
@@ -66,8 +71,13 @@
             return;
         }
 
-        HttpProxy p = new HttpProxy(host, port);
-        p.test();
+        try {
+            HttpProxy p = new HttpProxy(host, port);
+            p.test();
+        } finally {
+            if (proxy != null)
+                proxy.close();
+        }
     }
 
     public HttpProxy(String proxyHost, int proxyPort) {
@@ -79,26 +89,37 @@
         InetSocketAddress proxyAddress = new InetSocketAddress(proxyHost, proxyPort);
         Proxy httpProxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
 
-        try (ServerSocket ss = new ServerSocket(0);
-             Socket sock = new Socket(httpProxy)) {
-            sock.setSoTimeout(SO_TIMEOUT);
-            sock.setTcpNoDelay(false);
+        try (ServerSocket ss = new ServerSocket(0)) {
+            List<InetSocketAddress> externalAddresses = new ArrayList<>();
+            externalAddresses.add(
+                new InetSocketAddress(InetAddress.getLocalHost(), ss.getLocalPort()));
 
-            InetSocketAddress externalAddress =
-                new InetSocketAddress(InetAddress.getLocalHost(), ss.getLocalPort());
+            if (!"true".equals(System.getProperty("java.net.preferIPv4Stack"))) {
+                byte[] bytes = new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+                var address = InetAddress.getByAddress(bytes);
+                externalAddresses.add(
+                        new InetSocketAddress(address, ss.getLocalPort()));
+            }
 
-            out.println("Trying to connect to server socket on " + externalAddress);
-            sock.connect(externalAddress);
-            try (Socket externalSock = ss.accept()) {
-                // perform some simple checks
-                check(sock.isBound(), "Socket is not bound");
-                check(sock.isConnected(), "Socket is not connected");
-                check(!sock.isClosed(), "Socket should not be closed");
-                check(sock.getSoTimeout() == SO_TIMEOUT,
-                        "Socket should have a previously set timeout");
-                check(sock.getTcpNoDelay() ==  false, "NODELAY should be false");
+            for (SocketAddress externalAddress : externalAddresses) {
+                try (Socket sock = new Socket(httpProxy)) {
+                    sock.setSoTimeout(SO_TIMEOUT);
+                    sock.setTcpNoDelay(false);
 
-                simpleDataExchange(sock, externalSock);
+                    out.println("Trying to connect to server socket on " + externalAddress);
+                    sock.connect(externalAddress);
+                    try (Socket externalSock = ss.accept()) {
+                        // perform some simple checks
+                        check(sock.isBound(), "Socket is not bound");
+                        check(sock.isConnected(), "Socket is not connected");
+                        check(!sock.isClosed(), "Socket should not be closed");
+                        check(sock.getSoTimeout() == SO_TIMEOUT,
+                                "Socket should have a previously set timeout");
+                        check(sock.getTcpNoDelay() == false, "NODELAY should be false");
+
+                        simpleDataExchange(sock, externalSock);
+                    }
+                }
             }
         }
     }
@@ -108,7 +129,7 @@
     }
 
     static Exception unexpected(Exception e) {
-        out.println("Unexcepted Exception: " + e);
+        out.println("Unexpected Exception: " + e);
         e.printStackTrace();
         return e;
     }
@@ -164,9 +185,10 @@
         return i1 * 256 + i2;
     }
 
-    static class ConnectProxyTunnelServer extends Thread {
+    static class ConnectProxyTunnelServer extends Thread implements AutoCloseable {
 
         private final ServerSocket ss;
+        private volatile boolean closed;
 
         public ConnectProxyTunnelServer() throws IOException {
             ss = new ServerSocket(0);
@@ -174,13 +196,20 @@
 
         @Override
         public void run() {
-            try (Socket clientSocket = ss.accept()) {
-                processRequest(clientSocket);
+            try {
+                while (!closed) {
+                    try (Socket clientSocket = ss.accept()) {
+                        processRequest(clientSocket);
+                    }
+                }
             } catch (Exception e) {
-                out.println("Proxy Failed: " + e);
-                e.printStackTrace();
+                if (!closed) {
+                    out.println("Proxy Failed: " + e);
+                    e.printStackTrace();
+                }
             } finally {
-                try { ss.close(); } catch (IOException x) { unexpected(x); }
+                if (!closed)
+                    try { ss.close(); } catch (IOException x) { unexpected(x); }
             }
         }
 
@@ -191,6 +220,12 @@
             return ss.getLocalPort();
         }
 
+        @Override
+        public void close() throws Exception {
+            closed = true;
+            ss.close();
+        }
+
         /*
          * Processes the CONNECT request
          */
@@ -200,7 +235,7 @@
 
             if (!statusLine.startsWith("CONNECT")) {
                 out.println("proxy server: processes only "
-                                  + "CONNECT method requests, recieved: "
+                                  + "CONNECT method requests, received: "
                                   + statusLine);
                 return;
             }
@@ -246,12 +281,19 @@
                 int endi = connectStr.lastIndexOf(' ');
                 String connectInfo = connectStr.substring(starti+1, endi).trim();
                 // retrieve server name and port
-                endi = connectInfo.indexOf(':');
+                endi = connectInfo.lastIndexOf(':');
                 String name = connectInfo.substring(0, endi);
+
+                if (name.contains(":")) {
+                    if (!(name.startsWith("[") && name.endsWith("]"))) {
+                        throw new IOException("Invalid host:" + name);
+                    }
+                    name = name.substring(1, name.length() - 1);
+                }
                 int port = Integer.parseInt(connectInfo.substring(endi+1));
                 return new InetSocketAddress(name, port);
             } catch (Exception e) {
-                out.println("Proxy recieved a request: " + connectStr);
+                out.println("Proxy received a request: " + connectStr);
                 throw unexpected(e);
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/Timeouts.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * @run testng Timeouts
+ * @summary Test Socket timeouts
+ */
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+import jdk.test.lib.Utils;
+
+@Test
+public class Timeouts {
+
+    /**
+     * Test timed connect where connection is established
+     */
+    public void testTimedConnect1() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            try (Socket s = new Socket()) {
+                s.connect(ss.getLocalSocketAddress(), 2000);
+            }
+        }
+    }
+
+    /**
+     * Test timed connect where connection is refused
+     */
+    public void testTimedConnect2() throws IOException {
+        try (Socket s = new Socket()) {
+            SocketAddress remote = Utils.refusingEndpoint();
+            try {
+                s.connect(remote, 2000);
+            } catch (ConnectException expected) { }
+        }
+    }
+
+    /**
+     * Test connect with a timeout of Integer.MAX_VALUE
+     */
+    public void testTimedConnect3() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            try (Socket s = new Socket()) {
+                s.connect(ss.getLocalSocketAddress(), Integer.MAX_VALUE);
+            }
+        }
+    }
+
+    /**
+     * Test connect with a negative timeout. This case is not currently specified
+     * but the long standing behavior is to throw IllegalArgumentException.
+     */
+    public void testTimedConnect4() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            try (Socket s = new Socket()) {
+                try {
+                    s.connect(ss.getLocalSocketAddress(), -1);
+                    assertTrue(false);
+                } catch (IllegalArgumentException expected) { }
+            }
+        }
+    }
+
+    /**
+     * Test timed read where the read succeeds immediately
+     */
+    public void testTimedRead1() throws IOException {
+        withConnection((s1, s2) -> {
+            s1.getOutputStream().write(99);
+            s2.setSoTimeout(30*1000);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+        });
+    }
+
+    /**
+     * Test timed read where the read succeeds after a delay
+     */
+    public void testTimedRead2() throws IOException {
+        withConnection((s1, s2) -> {
+            scheduleWrite(s1.getOutputStream(), 99, 2000);
+            s2.setSoTimeout(30*1000);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+        });
+    }
+
+    /**
+     * Test timed read where the read times out
+     */
+    public void testTimedRead3() throws IOException {
+        withConnection((s1, s2) -> {
+            s2.setSoTimeout(2000);
+            try {
+                s2.getInputStream().read();
+                assertTrue(false);
+            } catch (SocketTimeoutException expected) { }
+        });
+    }
+
+    /**
+     * Test timed read that succeeds after a previous read has timed out
+     */
+    public void testTimedRead4() throws IOException {
+        withConnection((s1, s2) -> {
+            s2.setSoTimeout(2000);
+            try {
+                s2.getInputStream().read();
+                assertTrue(false);
+            } catch (SocketTimeoutException e) { }
+            s1.getOutputStream().write(99);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+        });
+    }
+
+    /**
+     * Test timed read that succeeds after a previous read has timed out and
+     * after a short delay
+     */
+    public void testTimedRead5() throws IOException {
+        withConnection((s1, s2) -> {
+            s2.setSoTimeout(2000);
+            try {
+                s2.getInputStream().read();
+                assertTrue(false);
+            } catch (SocketTimeoutException e) { }
+            s2.setSoTimeout(30*3000);
+            scheduleWrite(s1.getOutputStream(), 99, 2000);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+        });
+    }
+
+    /**
+     * Test untimed read that succeeds after a previous read has timed out
+     */
+    public void testTimedRead6() throws IOException {
+        withConnection((s1, s2) -> {
+            s2.setSoTimeout(2000);
+            try {
+                s2.getInputStream().read();
+                assertTrue(false);
+            } catch (SocketTimeoutException e) { }
+            s1.getOutputStream().write(99);
+            s2.setSoTimeout(0);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+        });
+    }
+
+    /**
+     * Test untimed read that succeeds after a previous read has timed out and
+     * after a short delay
+     */
+    public void testTimedRead7() throws IOException {
+        withConnection((s1, s2) -> {
+            s2.setSoTimeout(2000);
+            try {
+                s2.getInputStream().read();
+                assertTrue(false);
+            } catch (SocketTimeoutException e) { }
+            scheduleWrite(s1.getOutputStream(), 99, 2000);
+            s2.setSoTimeout(0);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+        });
+    }
+
+    /**
+     * Test async close of timed read
+     */
+    public void testTimedRead8() throws IOException {
+        withConnection((s1, s2) -> {
+            s2.setSoTimeout(30*1000);
+            scheduleClose(s2, 2000);
+            try {
+                s2.getInputStream().read();
+                assertTrue(false);
+            } catch (SocketException expected) { }
+        });
+    }
+
+    /**
+     * Test read with a timeout of Integer.MAX_VALUE
+     */
+    public void testTimedRead9() throws IOException {
+        withConnection((s1, s2) -> {
+            scheduleWrite(s1.getOutputStream(), 99, 2000);
+            s2.setSoTimeout(Integer.MAX_VALUE);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+        });
+    }
+
+    /**
+     * Test writing after a timed read.
+     */
+    public void testTimedWrite1() throws IOException {
+        withConnection((s1, s2) -> {
+            s1.getOutputStream().write(99);
+            s2.setSoTimeout(3000);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+
+            // schedule thread to read s1 to EOF
+            scheduleReadToEOF(s1.getInputStream(), 3000);
+
+            // write a lot so that write blocks
+            byte[] data = new byte[128*1024];
+            for (int i = 0; i < 100; i++) {
+                s2.getOutputStream().write(data);
+            }
+        });
+    }
+
+    /**
+     * Test async close of writer (after a timed read).
+     */
+    public void testTimedWrite2() throws IOException {
+        withConnection((s1, s2) -> {
+            s1.getOutputStream().write(99);
+            s2.setSoTimeout(3000);
+            int b = s2.getInputStream().read();
+            assertTrue(b == 99);
+
+            // schedule s2 to be be closed
+            scheduleClose(s2, 3000);
+
+            // write a lot so that write blocks
+            byte[] data = new byte[128*1024];
+            try {
+                while (true) {
+                    s2.getOutputStream().write(data);
+                }
+            } catch (SocketException expected) { }
+        });
+    }
+
+    /**
+     * Test timed accept where a connection is established immediately
+     */
+    public void testTimedAccept1() throws IOException {
+        Socket s1 = null;
+        Socket s2 = null;
+        try (ServerSocket ss = new ServerSocket(0)) {
+            s1 = new Socket();
+            s1.connect(ss.getLocalSocketAddress());
+            ss.setSoTimeout(30*1000);
+            s2 = ss.accept();
+        } finally {
+            if (s1 != null) s1.close();
+            if (s2 != null) s2.close();
+        }
+    }
+
+    /**
+     * Test timed accept where a connection is established after a short delay
+     */
+    public void testTimedAccept2() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            ss.setSoTimeout(30*1000);
+            scheduleConnect(ss.getLocalSocketAddress(), 2000);
+            Socket s = ss.accept();
+            s.close();
+        }
+    }
+
+    /**
+     * Test timed accept where the accept times out
+     */
+    public void testTimedAccept3() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            ss.setSoTimeout(2000);
+            try {
+                Socket s = ss.accept();
+                s.close();
+                assertTrue(false);
+            } catch (SocketTimeoutException expected) { }
+        }
+    }
+
+    /**
+     * Test timed accept where a connection is established immediately after a
+     * previous accept timed out.
+     */
+    public void testTimedAccept4() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            ss.setSoTimeout(2000);
+            try {
+                Socket s = ss.accept();
+                s.close();
+                assertTrue(false);
+            } catch (SocketTimeoutException expected) { }
+            try (Socket s1 = new Socket()) {
+                s1.connect(ss.getLocalSocketAddress());
+                Socket s2 = ss.accept();
+                s2.close();
+            }
+        }
+    }
+
+    /**
+     * Test untimed accept where a connection is established after a previous
+     * accept timed out
+     */
+    public void testTimedAccept5() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            ss.setSoTimeout(2000);
+            try {
+                Socket s = ss.accept();
+                s.close();
+                assertTrue(false);
+            } catch (SocketTimeoutException expected) { }
+            ss.setSoTimeout(0);
+            try (Socket s1 = new Socket()) {
+                s1.connect(ss.getLocalSocketAddress());
+                Socket s2 = ss.accept();
+                s2.close();
+            }
+        }
+    }
+
+    /**
+     * Test untimed accept where a connection is established after a previous
+     * accept timed out and after a short delay
+     */
+    public void testTimedAccept6() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            ss.setSoTimeout(2000);
+            try {
+                Socket s = ss.accept();
+                s.close();
+                assertTrue(false);
+            } catch (SocketTimeoutException expected) { }
+            ss.setSoTimeout(0);
+            scheduleConnect(ss.getLocalSocketAddress(), 2000);
+            Socket s = ss.accept();
+            s.close();
+        }
+    }
+
+    /**
+     * Test async close of a timed accept
+     */
+    public void testTimedAccept7() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            ss.setSoTimeout(30*1000);
+            scheduleClose(ss, 2000);
+            try {
+                ss.accept().close();
+                assertTrue(false);
+            } catch (SocketException expected) { }
+        }
+    }
+
+    /**
+     * Test Socket setSoTimeout with a negative timeout. This case is not currently
+     * specified but the long standing behavior is to throw IllegalArgumentException.
+     */
+    @Test(expectedExceptions = { IllegalArgumentException.class })
+    public void testBadTimeout1() throws IOException {
+        try (Socket s = new Socket()) {
+            s.setSoTimeout(-1);
+        }
+    }
+
+    /**
+     * Test ServerSocket setSoTimeout with a negative timeout. This case is not
+     * currently specified but the long standing behavior is to throw
+     * IllegalArgumentException.
+     */
+    @Test(expectedExceptions = { IllegalArgumentException.class })
+    public void testBadTimeout2() throws IOException {
+        try (ServerSocket ss = new ServerSocket()) {
+            ss.setSoTimeout(-1);
+        }
+    }
+
+    interface ThrowingBiConsumer<T, U> {
+        void accept(T t, U u) throws IOException;
+    }
+
+    /**
+     * Invokes the consumer with a connected pair of sockets
+     */
+    static void withConnection(ThrowingBiConsumer<Socket, Socket> consumer)
+        throws IOException
+    {
+        Socket s1 = null;
+        Socket s2 = null;
+        try (ServerSocket ss = new ServerSocket(0)) {
+            s1 = new Socket();
+            s1.connect(ss.getLocalSocketAddress());
+            s2 = ss.accept();
+            consumer.accept(s1, s2);
+        } finally {
+            if (s1 != null) s1.close();
+            if (s2 != null) s2.close();
+        }
+    }
+
+    /**
+     * Schedule c to be closed after a delay
+     */
+    static void scheduleClose(Closeable c, long delay) {
+        schedule(() -> {
+            try {
+                c.close();
+            } catch (IOException ioe) { }
+        }, delay);
+    }
+
+    /**
+     * Schedule a thread to connect to the given end point after a delay
+     */
+    static void scheduleConnect(SocketAddress remote, long delay) {
+        schedule(() -> {
+            try (Socket s = new Socket()) {
+                s.connect(remote);
+            } catch (IOException ioe) { }
+        }, delay);
+    }
+
+    /**
+     * Schedule a thread to read to EOF after a delay
+     */
+    static void scheduleReadToEOF(InputStream in, long delay) {
+        schedule(() -> {
+            byte[] bytes = new byte[8192];
+            try {
+                while (in.read(bytes) != -1) { }
+            } catch (IOException ioe) { }
+        }, delay);
+    }
+
+    /**
+     * Schedule a thread to write after a delay
+     */
+    static void scheduleWrite(OutputStream out, byte[] data, long delay) {
+        schedule(() -> {
+            try {
+                out.write(data);
+            } catch (IOException ioe) { }
+        }, delay);
+    }
+    static void scheduleWrite(OutputStream out, int b, long delay) {
+        scheduleWrite(out, new byte[] { (byte)b }, delay);
+    }
+
+    static void schedule(Runnable task, long delay) {
+        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+        try {
+            executor.schedule(task, delay, TimeUnit.MILLISECONDS);
+        } finally {
+            executor.shutdown();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/UdpSocket.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @run main UdpSocket
+ * @summary Basic test for a Socket to a UDP socket
+ */
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+import java.util.Arrays;
+
+public class UdpSocket {
+
+    static final String MESSAGE = "hello";
+
+    public static void main(String[] args) throws IOException {
+        try (DatagramChannel dc = DatagramChannel.open()) {
+            var loopback = InetAddress.getLoopbackAddress();
+            dc.bind(new InetSocketAddress(loopback, 0));
+
+            int port = ((InetSocketAddress) dc.getLocalAddress()).getPort();
+            try (Socket s = new Socket(loopback, port, false)) {
+
+                // send datagram with socket output stream
+                byte[] array1 = MESSAGE.getBytes("UTF-8");
+                s.getOutputStream().write(array1);
+
+                // receive the datagram
+                var buf = ByteBuffer.allocate(100);
+                SocketAddress remote = dc.receive(buf);
+                buf.flip();
+                if (buf.remaining() != MESSAGE.length())
+                    throw new RuntimeException("Unexpected size");
+
+                // echo the datagram
+                dc.send(buf, remote);
+
+                // receive datagram with the socket input stream
+                byte[] array2 = new byte[100];
+                int n = s.getInputStream().read(array2);
+                if (n != MESSAGE.length())
+                    throw new RuntimeException("Unexpected size");
+                if (!Arrays.equals(array1, 0, n, array2, 0, n))
+                    throw new RuntimeException("Unexpected contents");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/SocketImpl/SocketImplCombinations.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,844 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8220493
+ * @modules java.base/java.net:+open java.base/sun.nio.ch:+open
+ * @run testng/othervm SocketImplCombinations
+ * @summary Test Socket and ServerSocket with combinations of SocketImpls
+ */
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketImpl;
+import java.net.SocketImplFactory;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.function.BiConsumer;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class SocketImplCombinations {
+
+    /**
+     * Test creating an unconnected Socket, it should be created with a platform SocketImpl.
+     */
+    public void testNewSocket1() throws IOException {
+        try (Socket s = new Socket()) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isSocksSocketImpl(si));
+            SocketImpl delegate = getDelegate(si);
+            assertTrue(isPlatformSocketImpl(delegate));
+        }
+    }
+
+    /**
+     * Test creating a connected Socket, it should be created with a platform SocketImpl.
+     */
+    public void testNewSocket2() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            try (Socket s = new Socket(ss.getInetAddress(), ss.getLocalPort())) {
+                SocketImpl si = getSocketImpl(s);
+                assertTrue(isSocksSocketImpl(si));
+                SocketImpl delegate = getDelegate(si);
+                assertTrue(isPlatformSocketImpl(delegate));
+            }
+        }
+    }
+
+    /**
+     * Test creating a Socket for a DIRECT connection, it should be created with a
+     * platform SocketImpl.
+     */
+    public void testNewSocket3() throws IOException {
+        try (Socket s = new Socket(Proxy.NO_PROXY)) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isPlatformSocketImpl(si));
+        }
+    }
+
+    /**
+     * Test creating a Socket for a SOCKS connection, it should be created with a
+     * SOCKS SocketImpl.
+     */
+    public void testNewSocket4() throws IOException {
+        var address = new InetSocketAddress("127.0.0.1", 1080);
+        var socksProxy = new Proxy(Proxy.Type.SOCKS, address);
+        try (Socket s = new Socket(socksProxy)) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isSocksSocketImpl(si));
+            SocketImpl delegate = getDelegate(si);
+            assertTrue(isPlatformSocketImpl(delegate));
+        }
+    }
+
+    /**
+     * Test creating a Socket for a HTTP proxy connection, it should be created with
+     * a HTTP proxy SocketImpl.
+     */
+    public void testNewSocket5() throws IOException {
+        var address = new InetSocketAddress("127.0.0.1", 8080);
+        var httpProxy = new Proxy(Proxy.Type.HTTP, address);
+        try (Socket s = new Socket(httpProxy)) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isHttpConnectSocketImpl(si));
+            SocketImpl delegate = getDelegate(si);
+            assertTrue(isPlatformSocketImpl(delegate));
+        }
+    }
+
+    /**
+     * Test creating a Socket no SocketImpl. A platform SocketImpl should be
+     * created lazily.
+     */
+    public void testNewSocket6() throws IOException {
+        Socket s = new Socket((SocketImpl) null) { };
+        try (s) {
+            assertTrue(getSocketImpl(s) == null);
+            s.bind(new InetSocketAddress(0));   // force SocketImpl to be created
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isSocksSocketImpl(si));
+            SocketImpl delegate = getDelegate(si);
+            assertTrue(isPlatformSocketImpl(delegate));
+        }
+    }
+
+    /**
+     * Test creating a Socket with a custom SocketImpl.
+     */
+    public void testNewSocket7() throws IOException {
+        Socket s = new Socket(new CustomSocketImpl(false)) { };
+        try (s) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(si instanceof CustomSocketImpl);
+        }
+    }
+
+    /**
+     * Test creating a Socket when there is a SocketImplFactory set.
+     */
+    public void testNewSocket8() throws IOException {
+        setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
+        try (Socket s = new Socket()) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(si instanceof CustomSocketImpl);
+        } finally {
+            setSocketSocketImplFactory(null);
+        }
+    }
+
+    /**
+     * Test creating a Socket for a DIRECT connection when there is a
+     * SocketImplFactory set.
+     */
+    public void testNewSocket9() throws IOException {
+        setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
+        try (Socket s = new Socket(Proxy.NO_PROXY)) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(si instanceof CustomSocketImpl);
+        } finally {
+            setSocketSocketImplFactory(null);
+        }
+    }
+
+    /**
+     * Test creating a Socket for a SOCKS connection when there is a
+     * SocketImplFactory set.
+     */
+    public void testNewSocket10() throws IOException {
+        var address = new InetSocketAddress("127.0.0.1", 1080);
+        var socksProxy = new Proxy(Proxy.Type.SOCKS, address);
+        setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
+        try (Socket s = new Socket(socksProxy)) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isSocksSocketImpl(si));
+            SocketImpl delegate = getDelegate(si);
+            assertTrue(isPlatformSocketImpl(delegate));
+        } finally {
+            setSocketSocketImplFactory(null);
+        }
+    }
+
+    /**
+     * Test creating a Socket for a HTTP proxy connection when there is a
+     * SocketImplFactory set.
+     */
+    public void testNewSocket11() throws IOException {
+        var address = new InetSocketAddress("127.0.0.1", 8080);
+        var httpProxy = new Proxy(Proxy.Type.HTTP, address);
+        setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
+        try (Socket s = new Socket(httpProxy)) {
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isHttpConnectSocketImpl(si));
+            SocketImpl delegate = getDelegate(si);
+            assertTrue(isPlatformSocketImpl(delegate));
+        } finally {
+            setSocketSocketImplFactory(null);
+        }
+    }
+
+    /**
+     * Test creating a Socket no SocketImpl when there is a SocketImplFactory set.
+     */
+    public void testNewSocket12() throws IOException {
+        setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
+        try {
+            Socket s = new Socket((SocketImpl) null) { };
+            try (s) {
+                assertTrue(getSocketImpl(s) == null);
+                s.bind(new InetSocketAddress(0));   // force SocketImpl to be created
+                assertTrue(getSocketImpl(s) instanceof CustomSocketImpl);
+            }
+        } finally {
+            setSocketSocketImplFactory(null);
+        }
+    }
+
+    /**
+     * Test creating an unbound ServerSocket, it should be created with a platform
+     * SocketImpl.
+     */
+    public void testNewServerSocket1() throws IOException {
+        try (ServerSocket ss = new ServerSocket()) {
+            SocketImpl si = getSocketImpl(ss);
+            assertTrue(isPlatformSocketImpl(si));
+        }
+    }
+
+    /**
+     * Test creating a bound ServerSocket, it should be created with a platform
+     * SocketImpl.
+     */
+    public void testNewServerSocket2() throws IOException {
+        try (ServerSocket ss = new ServerSocket(0)) {
+            SocketImpl si = getSocketImpl(ss);
+            assertTrue(isPlatformSocketImpl(si));
+        }
+    }
+
+    /**
+     * Test creating a ServerSocket with a custom SocketImpl.
+     */
+    public void testNewServerSocket3() throws IOException {
+        ServerSocket ss = new ServerSocket(new CustomSocketImpl(true)) { };
+        try (ss) {
+            SocketImpl si = getSocketImpl(ss);
+            assertTrue(si instanceof CustomSocketImpl);
+        }
+    }
+
+    /**
+     * Test creating an unbound ServerSocket when there is a SocketImplFactory set.
+     */
+    public void testNewServerSocket4() throws IOException {
+        setServerSocketImplFactory(() -> new CustomSocketImpl(true));
+        try (ServerSocket ss = new ServerSocket()) {
+            SocketImpl si = getSocketImpl(ss);
+            assertTrue(si instanceof CustomSocketImpl);
+        } finally {
+            setServerSocketImplFactory(null);
+        }
+    }
+
+    /**
+     * Test creating a bound ServerSocket when there is a SocketImplFactory set.
+     */
+    public void testNewServerSocket5() throws IOException {
+        setServerSocketImplFactory(() -> new CustomSocketImpl(true));
+        try (ServerSocket ss = new ServerSocket(0)) {
+            SocketImpl si = getSocketImpl(ss);
+            assertTrue(si instanceof CustomSocketImpl);
+        } finally {
+            setServerSocketImplFactory(null);
+        }
+    }
+
+    /**
+     * Test ServerSocket.accept. The ServerSocket uses a platform SocketImpl,
+     * the Socket to accept is created with no SocketImpl.
+     */
+    public void testServerSocketAccept1() throws IOException {
+        var socket = new Socket((SocketImpl) null) { };
+        assertTrue(getSocketImpl(socket) == null);
+
+        serverSocketAccept(socket, (ss, s) -> {
+            assertTrue(isPlatformSocketImpl(getSocketImpl(ss)));
+            assertTrue(s == socket);
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isPlatformSocketImpl(si));
+            checkFields(si);
+        });
+    }
+
+    /**
+     * Test ServerSocket.accept. The ServerSocket uses a platform SocketImpl,
+     * the Socket to accept is created with no SocketImpl, and there is a custom
+     * client SocketImplFactory set.
+     */
+    public void testServerSocketAccept2() throws IOException {
+        var socket = new Socket((SocketImpl) null) { };
+        assertTrue(getSocketImpl(socket) == null);
+
+        serverSocketAccept(socket, () -> new CustomSocketImpl(false), (ss, s) -> {
+            assertTrue(isPlatformSocketImpl(getSocketImpl(ss)));
+            assertTrue(s == socket);
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(isPlatformSocketImpl(si));
+            checkFields(si);
+        });
+    }
+
+    /**
+     * Test ServerSocket.accept. The ServerSocket uses a platform SocketImpl,
+     * the Socket to accept is created with a SocketImpl that delegates to a
+     * platform SocketImpl.
+     */
+    public void testServerSocketAccept3() throws IOException {
+        var socket = new Socket();
+        SocketImpl si = getSocketImpl(socket);
+        assertTrue(isSocksSocketImpl(si));
+        SocketImpl delegate = getDelegate(si);
+        assertTrue(isPlatformSocketImpl(delegate));
+
+        serverSocketAccept(socket, (ss, s) -> {
+            assertTrue(isPlatformSocketImpl(getSocketImpl(ss)));
+            assertTrue(s == socket);
+            SocketImpl psi = getSocketImpl(socket);
+            assertTrue(isPlatformSocketImpl(psi));
+            checkFields(psi);
+        });
+    }
+
+    /**
+     * Test ServerSocket.accept. The ServerSocket uses a platform SocketImpl,
+     * the Socket to accept is created with a custom SocketImpl.
+     */
+    public void testServerSocketAccept4a() throws IOException {
+        SocketImpl clientImpl = new CustomSocketImpl(false);
+        Socket socket = new Socket(clientImpl) { };
+        assertTrue(getSocketImpl(socket) == clientImpl);
+
+        try (ServerSocket ss = serverSocketToAccept(socket)) {
+            expectThrows(IOException.class, ss::accept);
+        } finally {
+            socket.close();
+        }
+    }
+
+    public void testServerSocketAccept4b() throws IOException {
+        SocketImpl clientImpl = new CustomSocketImpl(false);
+        Socket socket = new Socket(clientImpl) { };
+        assertTrue(getSocketImpl(socket) == clientImpl);
+
+        setSocketSocketImplFactory(() -> new CustomSocketImpl(false));
+        try (ServerSocket ss = serverSocketToAccept(socket)) {
+            expectThrows(IOException.class, ss::accept);
+        } finally {
+            setSocketSocketImplFactory(null);
+            socket.close();
+        }
+    }
+
+    /**
+     * Test ServerSocket.accept. The ServerSocket uses a custom SocketImpl,
+     * the Socket to accept is created no SocketImpl.
+     */
+    public void testServerSocketAccept5a() throws IOException {
+        SocketImpl serverImpl = new CustomSocketImpl(true);
+        try (ServerSocket ss = new ServerSocket(serverImpl) { }) {
+            ss.bind(new InetSocketAddress(0));
+            expectThrows(IOException.class, ss::accept);
+        }
+    }
+
+    public void testServerSocketAccept5b() throws IOException {
+        var socket = new Socket((SocketImpl) null) { };
+        assertTrue(getSocketImpl(socket) == null);
+
+        SocketImpl serverImpl = new CustomSocketImpl(true);
+        try (ServerSocket ss = serverSocketToAccept(serverImpl, socket)) {
+            expectThrows(IOException.class, ss::accept);
+        } finally {
+            socket.close();
+        }
+    }
+
+    public void testServerSocketAccept5c() throws IOException {
+        setServerSocketImplFactory(() -> new CustomSocketImpl(true));
+        try (ServerSocket ss = new ServerSocket(0)) {
+            expectThrows(IOException.class, ss::accept);
+        } finally {
+            setServerSocketImplFactory(null);
+        }
+    }
+
+    public void testServerSocketAccept5d() throws IOException {
+        var socket = new Socket((SocketImpl) null) { };
+        assertTrue(getSocketImpl(socket) == null);
+
+        setServerSocketImplFactory(() -> new CustomSocketImpl(true));
+        try (ServerSocket ss = serverSocketToAccept(socket)) {
+            expectThrows(IOException.class, ss::accept);
+        } finally {
+            setServerSocketImplFactory(null);
+            socket.close();
+        }
+    }
+
+    /**
+     * Test ServerSocket.accept. The ServerSocket uses a custom SocketImpl,
+     * the Socket to accept is created with no SocketImpl, and there is a custom
+     * client SocketImplFactory set.
+     */
+    public void testServerSocketAccept6() throws Exception {
+        var socket = new Socket((SocketImpl) null) { };
+        assertTrue(getSocketImpl(socket) == null);
+
+        SocketImpl serverImpl = new CustomSocketImpl(true);
+        SocketImplFactory clientFactory = () -> new CustomSocketImpl(false);
+        serverSocketAccept(serverImpl, socket, clientFactory, (ss, s) -> {
+            assertTrue(getSocketImpl(ss) == serverImpl);
+            SocketImpl si = getSocketImpl(s);
+            assertTrue(si instanceof CustomSocketImpl);
+            checkFields(si);
+        });
+    }
+
+    /**
+     * Test ServerSocket.accept. The ServerSocket uses a custom SocketImpl,
+     * the Socket to accept is created with a SocketImpl that delegates to a
+     * platform SocketImpl.
+     */
+    public void testServerSocketAccept7a() throws IOException {
+        var socket = new Socket();
+        SocketImpl si = getSocketImpl(socket);
+        assertTrue(isSocksSocketImpl(si));
+        SocketImpl delegate = getDelegate(si);
+        assertTrue(isPlatformSocketImpl(delegate));
+
+        SocketImpl serverImpl = new CustomSocketImpl(true);
+        try (ServerSocket ss = serverSocketToAccept(serverImpl, socket)) {
+            expectThrows(IOException.class, ss::accept);
+        } finally {
+            socket.close();
+        }
+    }
+
+    public void testServerSocketAccept7b() throws IOException {
+        var socket = new Socket();
+        SocketImpl si = getSocketImpl(socket);
+        assertTrue(isSocksSocketImpl(si));
+        SocketImpl delegate = getDelegate(si);
+        assertTrue(isPlatformSocketImpl(delegate));
+
+        setServerSocketImplFactory(() -> new CustomSocketImpl(true));
+        try (ServerSocket ss = serverSocketToAccept(socket)) {
+            expectThrows(IOException.class, ss::accept);
+        } finally {
+            setServerSocketImplFactory(null);
+            socket.close();
+        }
+    }
+
+    /**
+     * Test ServerSocket.accept. The ServerSocket uses a custom SocketImpl,
+     * the Socket to accept is created with a custom SocketImpl.
+     */
+    public void testServerSocketAccept8() throws Exception {
+        SocketImpl clientImpl = new CustomSocketImpl(false);
+        Socket socket = new Socket(clientImpl) { };
+        assertTrue(getSocketImpl(socket) == clientImpl);
+
+        SocketImpl serverImpl = new CustomSocketImpl(true);
+        SocketImplFactory clientFactory = () -> new CustomSocketImpl(false);
+        serverSocketAccept(serverImpl, socket, clientFactory, (ss, s) -> {
+            assertTrue(getSocketImpl(ss) == serverImpl);
+            assertTrue(getSocketImpl(s) == clientImpl);
+            checkFields(clientImpl);
+        });
+    }
+
+    /**
+     * Creates a ServerSocket that returns the given Socket from accept.
+     * The consumer is invoked with the server socket and the accepted socket.
+     */
+    static void serverSocketAccept(Socket socket,
+                                   BiConsumer<ServerSocket, Socket> consumer)
+        throws IOException
+    {
+        Socket s1 = null;
+        Socket s2 = null;
+        try (ServerSocket ss = serverSocketToAccept(socket)) {
+            s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
+            s2 = ss.accept();
+            consumer.accept(ss, s2);
+        } finally {
+            if (s1 != null) s1.close();
+            if (s2 != null) s2.close();
+        }
+    }
+
+    /**
+     * Creates a ServerSocket that returns the given Socket from accept. The
+     * given SocketImplFactory is set during the accept and the consumer is
+     * invoked when the server socket and the accepted socket.
+     */
+    static void serverSocketAccept(Socket socket,
+                                   SocketImplFactory factory,
+                                   BiConsumer<ServerSocket, Socket> consumer)
+        throws IOException
+    {
+        Socket s1 = null;
+        Socket s2 = null;
+        try (ServerSocket ss = serverSocketToAccept(socket)) {
+            s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
+            setSocketSocketImplFactory(factory);
+            try {
+                s2 = ss.accept();
+            } finally {
+                setSocketSocketImplFactory(null);
+            }
+            consumer.accept(ss, s2);
+        } finally {
+            if (s1 != null) s1.close();
+            if (s2 != null) s2.close();
+        }
+    }
+
+    /**
+     * Creates a ServerSocket with a SocketImpl returns the given Socket from
+     * accept. The given SocketImplFactory is set during the accept and the
+     * consumer is invoked when the server socket and the accepted socket.
+     */
+    static void serverSocketAccept(SocketImpl impl,
+                                   Socket socket,
+                                   SocketImplFactory factory,
+                                   BiConsumer<ServerSocket, Socket> consumer)
+        throws IOException
+    {
+        Socket s1 = null;
+        Socket s2 = null;
+        try (ServerSocket ss = serverSocketToAccept(impl, socket)) {
+            s1 = new Socket(ss.getInetAddress(), ss.getLocalPort());
+            setSocketSocketImplFactory(factory);
+            try {
+                s2 = ss.accept();
+            } finally {
+                setSocketSocketImplFactory(null);
+            }
+            consumer.accept(ss, s2);
+        } finally {
+            if (s1 != null) s1.close();
+            if (s2 != null) s2.close();
+        }
+    }
+
+    /**
+     * Creates a ServerSocket that returns the given Socket from accept.
+     */
+    static ServerSocket serverSocketToAccept(Socket s) throws IOException {
+        return new ServerSocket(0) {
+            @Override
+            public Socket accept() throws IOException {
+                implAccept(s);
+                return s;
+            }
+        };
+    }
+
+    /**
+     * Creates a ServerSocket with a SocketImpl that returns the given Socket
+     * from accept.
+     */
+    static ServerSocket serverSocketToAccept(SocketImpl impl, Socket s) throws IOException {
+        ServerSocket ss = new ServerSocket(impl) {
+            @Override
+            public Socket accept() throws IOException {
+                implAccept(s);
+                return s;
+            }
+        };
+        ss.bind(new InetSocketAddress(0));
+        return ss;
+    }
+
+    /**
+     * Returns the socket's SocketImpl
+     */
+    static SocketImpl getSocketImpl(Socket s) {
+        try {
+            Field f = Socket.class.getDeclaredField("impl");
+            f.setAccessible(true);
+            return (SocketImpl) f.get(s);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns the server socket's SocketImpl
+     */
+    static SocketImpl getSocketImpl(ServerSocket ss) {
+        try {
+            Field f = ServerSocket.class.getDeclaredField("impl");
+            f.setAccessible(true);
+            return (SocketImpl) f.get(ss);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns the SocketImpl that the given SocketImpl delegates to
+     */
+    static SocketImpl getDelegate(SocketImpl si) {
+        try {
+            Class<?> clazz = Class.forName("java.net.DelegatingSocketImpl");
+            Field f = clazz.getDeclaredField("delegate");
+            f.setAccessible(true);
+            return (SocketImpl) f.get(si);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns the value of a SocketImpl field
+     */
+    static <T> T get(SocketImpl si, String name) {
+        try {
+            Field f = SocketImpl.class.getDeclaredField(name);
+            f.setAccessible(true);
+            return (T) f.get(si);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Sets the value of SocketImpl field
+     */
+    static void set(SocketImpl si, String name, Object value) {
+        try {
+            Field f = SocketImpl.class.getDeclaredField(name);
+            f.setAccessible(true);
+            f.set(si, value);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns true if the SocketImpl is a PlatformSocketImpl
+     */
+    static boolean isPlatformSocketImpl(SocketImpl si) {
+        try {
+            Class<?> clazz = Class.forName("sun.net.PlatformSocketImpl");
+            return clazz.isInstance(si);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns true if the SocketImpl is a SocksSocketImpl
+     */
+    static boolean isSocksSocketImpl(SocketImpl si) {
+        try {
+            Class<?> clazz = Class.forName("java.net.SocksSocketImpl");
+            return clazz.isInstance(si);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns true if the SocketImpl is a HttpConnectSocketImpl
+     */
+    static boolean isHttpConnectSocketImpl(SocketImpl si) {
+        try {
+            Class<?> clazz = Class.forName("java.net.HttpConnectSocketImpl");
+            return clazz.isInstance(si);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Socket.setSocketImplFactory(SocketImplFactory)
+     */
+    static void setSocketSocketImplFactory(SocketImplFactory factory) {
+        try {
+            Field f = Socket.class.getDeclaredField("factory");
+            f.setAccessible(true);
+            f.set(null, factory);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * ServerSocket.setSocketFactory(SocketImplFactory)
+     */
+    static void setServerSocketImplFactory(SocketImplFactory factory) {
+        try {
+            Field f = ServerSocket.class.getDeclaredField("factory");
+            f.setAccessible(true);
+            f.set(null, factory);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Checks the 4 protected fields of a SocketImpl to make sure that they
+     * have been initialized.
+     */
+    static void checkFields(SocketImpl si) {
+        FileDescriptor fd = get(si, "fd");
+        InetAddress address = get(si, "address");
+        int port = get(si, "port");
+        int localport = get(si, "localport");
+        assertTrue(fd.valid() && address != null && port != 0 && localport != 0);
+    }
+
+    /**
+     * Custom SocketImpl that is layed on a SocketChannel or ServerSocketChannel
+     */
+    static class CustomSocketImpl extends SocketImpl {
+        private final boolean server;
+        private ServerSocketChannel ssc;
+        private SocketChannel sc;
+
+        CustomSocketImpl(boolean server) {
+            this.server = server;
+        }
+
+        @Override
+        protected void create(boolean stream) throws IOException {
+            if (server) {
+                ssc = ServerSocketChannel.open();
+            } else {
+                sc = SocketChannel.open();
+            }
+        }
+
+        @Override
+        protected void connect(String host, int port) throws IOException {
+            connect(new InetSocketAddress(host, port), 0);
+        }
+
+        @Override
+        protected void connect(InetAddress address, int port) throws IOException {
+            connect(new InetSocketAddress(address, port), 0);
+        }
+
+        @Override
+        protected void connect(SocketAddress remote, int timeout) throws IOException {
+            sc.connect(remote);
+            super.address = ((InetSocketAddress) remote).getAddress();
+            super.port = ((InetSocketAddress) remote).getPort();
+        }
+
+        @Override
+        protected void bind(InetAddress address, int port) throws IOException {
+            if (server) {
+                ssc.bind(new InetSocketAddress(address, port));
+                super.localport = ssc.socket().getLocalPort();
+            } else {
+                sc.bind(new InetSocketAddress(address, port));
+                super.localport = sc.socket().getLocalPort();
+            }
+            super.address = address;
+        }
+
+        @Override
+        protected void listen(int backlog) {
+            // do nothing
+        }
+
+        @Override
+        protected void accept(SocketImpl si) throws IOException {
+            SocketChannel peer = ssc.accept();
+            FileDescriptor fd;
+            try {
+                Class<?> clazz = Class.forName("sun.nio.ch.SocketChannelImpl");
+                Field f = clazz.getDeclaredField("fd");
+                f.setAccessible(true);
+                fd = (FileDescriptor) f.get(peer);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+            set(si, "fd", fd);
+            set(si, "address", peer.socket().getInetAddress());
+            set(si, "port", peer.socket().getPort());
+            set(si, "localport", peer.socket().getLocalPort());
+        }
+
+        @Override
+        protected InputStream getInputStream() {
+            throw new RuntimeException();
+        }
+
+        @Override
+        protected OutputStream getOutputStream() {
+            throw new RuntimeException();
+        }
+
+        @Override
+        protected int available() {
+            return 0;
+        }
+
+        @Override
+        protected void close() {
+        }
+
+        @Override
+        protected void sendUrgentData(int data) {
+            throw new RuntimeException();
+        }
+
+        @Override
+        public void setOption(int option, Object value) {
+            throw new RuntimeException();
+        }
+
+        @Override
+        public Object getOption(int option) {
+            throw new RuntimeException();
+        }
+    }
+}
--- a/test/jdk/java/net/URL/HandlerLoop.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/net/URL/HandlerLoop.java	Tue Mar 26 09:05:10 2019 -0400
@@ -32,7 +32,7 @@
  * @summary Test bootstrap problem when a URLStreamHandlerFactory is loaded
  *          by the application class loader.
  * @modules java.base/sun.net.www.protocol.file
- * @run main HandlerLoop
+ * @run main/othervm HandlerLoop
  */
 public class HandlerLoop {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/nio/channels/SocketChannel/ConnectionReset.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @requires os.family != "solaris"
+ * @run testng ConnectionReset
+ * @summary Test behavior of SocketChannel.read and the Socket adaptor read
+ *          and available methods when a connection is reset
+ */
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.lang.reflect.Method;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class ConnectionReset {
+
+    static final int REPEAT_COUNT = 5;
+
+    /**
+     * Tests SocketChannel.read when the connection is reset and there are no
+     * bytes to read.
+     */
+    public void testSocketChannelReadNoData() throws IOException {
+        System.out.println("testSocketChannelReadNoData");
+        withResetConnection(null, sc -> {
+            ByteBuffer bb = ByteBuffer.allocate(100);
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                try {
+                    sc.read(bb);
+                    assertTrue(false);
+                } catch (IOException ioe) {
+                    System.out.format("read => %s (expected)%n", ioe);
+                }
+            }
+        });
+    }
+
+    /**
+     * Tests SocketChannel.read when the connection is reset and there are bytes
+     * to read.
+     */
+    public void testSocketChannelReadData() throws IOException {
+        System.out.println("testSocketChannelReadData");
+        byte[] data = { 1, 2, 3 };
+        withResetConnection(data, sc -> {
+            int remaining = data.length;
+            ByteBuffer bb = ByteBuffer.allocate(remaining + 100);
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                try {
+                    int bytesRead = sc.read(bb);
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                    } else {
+                        System.out.println("read => " + bytesRead + " byte(s)");
+                    }
+                    assertTrue(bytesRead > 0);
+                    remaining -= bytesRead;
+                    assertTrue(remaining >= 0);
+                } catch (IOException ioe) {
+                    System.out.format("read => %s%n", ioe);
+                    remaining = 0;
+                }
+            }
+        });
+    }
+
+
+    /**
+     * Tests available before Socket read when the connection is reset and there
+     * are no bytes to read.
+     */
+    public void testAvailableBeforeSocketReadNoData() throws IOException {
+        System.out.println("testAvailableBeforeSocketReadNoData");
+        withResetConnection(null, sc -> {
+            Socket s = sc.socket();
+            InputStream in = s.getInputStream();
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(bytesAvailable == 0);
+                try {
+                    int bytesRead = in.read();
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                    } else {
+                        System.out.println("read => 1 byte");
+                    }
+                    assertTrue(false);
+                } catch (IOException ioe) {
+                    System.out.format("read => %s (expected)%n", ioe);
+                }
+            }
+        });
+    }
+
+    /**
+     * Tests available before Socket read when the connection is reset and there
+     * are bytes to read.
+     */
+    public void testAvailableBeforeSocketReadData() throws IOException {
+        System.out.println("testAvailableBeforeSocketReadData");
+        byte[] data = { 1, 2, 3 };
+        withResetConnection(data, sc -> {
+            Socket s = sc.socket();
+            InputStream in = s.getInputStream();
+            int remaining = data.length;
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(bytesAvailable <= remaining);
+                try {
+                    int bytesRead = in.read();
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                        assertTrue(false);
+                    } else {
+                        System.out.println("read => 1 byte");
+                        assertTrue(remaining > 0);
+                        remaining--;
+                    }
+                } catch (IOException ioe) {
+                    System.out.format("read => %s%n", ioe);
+                    remaining = 0;
+                }
+            }
+        });
+    }
+
+    /**
+     * Tests Socket read before available when the connection is reset and there
+     * are no bytes to read.
+     */
+    public void testSocketReadNoDataBeforeAvailable() throws IOException {
+        System.out.println("testSocketReadNoDataBeforeAvailable");
+        withResetConnection(null, sc -> {
+            Socket s = sc.socket();
+            InputStream in = s.getInputStream();
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                try {
+                    int bytesRead = in.read();
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                    } else {
+                        System.out.println("read => 1 byte");
+                    }
+                    assertTrue(false);
+                } catch (IOException ioe) {
+                    System.out.format("read => %s (expected)%n", ioe);
+                }
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(bytesAvailable == 0);
+            }
+        });
+    }
+
+    /**
+     * Tests Socket read before available when the connection is reset and there
+     * are bytes to read.
+     */
+    public void testSocketReadDataBeforeAvailable() throws IOException {
+        System.out.println("testSocketReadDataBeforeAvailable");
+        byte[] data = { 1, 2, 3 };
+        withResetConnection(data, sc -> {
+            Socket s = sc.socket();
+            InputStream in = s.getInputStream();
+            int remaining = data.length;
+            for (int i=0; i<REPEAT_COUNT; i++) {
+                try {
+                    int bytesRead = in.read();
+                    if (bytesRead == -1) {
+                        System.out.println("read => EOF");
+                        assertTrue(false);
+                    } else {
+                        System.out.println("read => 1 byte");
+                        assertTrue(remaining > 0);
+                        remaining--;
+                    }
+                } catch (IOException ioe) {
+                    System.out.format("read => %s%n", ioe);
+                    remaining = 0;
+                }
+                int bytesAvailable = in.available();
+                System.out.format("available => %d%n", bytesAvailable);
+                assertTrue(bytesAvailable <= remaining);
+            }
+        });
+    }
+
+    interface ThrowingConsumer<T> {
+        void accept(T t) throws IOException;
+    }
+
+    /**
+     * Invokes a consumer with a SocketChannel connected to a peer that has closed
+     * the connection with a "connection reset". The peer sends the given data
+     * bytes before closing (when data is not null).
+     */
+    static void withResetConnection(byte[] data, ThrowingConsumer<SocketChannel> consumer)
+        throws IOException
+    {
+        var loopback = InetAddress.getLoopbackAddress();
+        try (var listener = new ServerSocket()) {
+            listener.bind(new InetSocketAddress(loopback, 0));
+            try (var sc = SocketChannel.open()) {
+                sc.connect(listener.getLocalSocketAddress());
+                try (Socket peer = listener.accept()) {
+                    if (data != null) {
+                        peer.getOutputStream().write(data);
+                    }
+                    peer.setSoLinger(true, 0);
+                }
+                consumer.accept(sc);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/text/Format/NumberFormat/DFSMinusPerCentMill.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8220309
+ * @library /java/text/testlib
+ * @summary Test String representation of MinusSign/Percent/PerMill symbols.
+ *          This test assumes CLDR has numbering systems for "arab" and
+ *          "arabext", and their minus/percent representations include
+ *          BiDi formatting control characters.
+ * @run testng/othervm DFSMinusPerCentMill
+ */
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class DFSMinusPerCentMill {
+    private enum Type {
+        NUMBER, PERCENT, CURRENCY, INTEGER, COMPACT, PERMILL
+    }
+
+    private static final Locale US_ARAB = Locale.forLanguageTag("en-US-u-nu-arab");
+    private static final Locale US_ARABEXT = Locale.forLanguageTag("en-US-u-nu-arabext");
+    private static final double SRC_NUM = -1234.56;
+
+    @DataProvider
+    Object[][] formatData() {
+        return new Object[][] {
+            // Locale, FormatStyle, expected format, expected single char symbol
+            {US_ARAB, Type.NUMBER, "\u061c-\u0661\u066c\u0662\u0663\u0664\u066b\u0665\u0666"},
+            {US_ARAB, Type.PERCENT, "\u061c-\u0661\u0662\u0663\u066c\u0664\u0665\u0666\u066a\u061c"},
+            {US_ARAB, Type.CURRENCY, "\u061c-$\u0661\u066c\u0662\u0663\u0664\u066b\u0665\u0666"},
+            {US_ARAB, Type.INTEGER, "\u061c-\u0661\u066c\u0662\u0663\u0665"},
+            {US_ARAB, Type.COMPACT, "\u061c-\u0661K"},
+            {US_ARAB, Type.PERMILL, "\u061c-\u0661\u0662\u0663\u0664\u0665\u0666\u0660\u0609"},
+
+            {US_ARABEXT, Type.NUMBER, "\u200e-\u200e\u06f1\u066c\u06f2\u06f3\u06f4\u066b\u06f5\u06f6"},
+            {US_ARABEXT, Type.PERCENT, "\u200e-\u200e\u06f1\u06f2\u06f3\u066c\u06f4\u06f5\u06f6\u066a"},
+            {US_ARABEXT, Type.CURRENCY, "\u200e-\u200e$\u06f1\u066c\u06f2\u06f3\u06f4\u066b\u06f5\u06f6"},
+            {US_ARABEXT, Type.INTEGER, "\u200e-\u200e\u06f1\u066c\u06f2\u06f3\u06f5"},
+            {US_ARABEXT, Type.COMPACT, "\u200e-\u200e\u06f1K"},
+            {US_ARABEXT, Type.PERMILL, "\u200e-\u200e\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f0\u0609"},
+        };
+    }
+
+    @DataProvider
+    Object[][] charSymbols() {
+        return new Object[][]{
+            // Locale, percent, per mille, minus sign
+            {US_ARAB, '\u066a', '\u0609', '-'},
+            {US_ARABEXT, '\u066a', '\u0609', '-'},
+        };
+    }
+
+    @Test(dataProvider="formatData")
+    public void testFormatData(Locale l, Type style, String expected) {
+        NumberFormat nf = null;
+        switch (style) {
+            case NUMBER:
+                nf = NumberFormat.getNumberInstance(l);
+                break;
+            case PERCENT:
+                nf = NumberFormat.getPercentInstance(l);
+                break;
+            case CURRENCY:
+                nf = NumberFormat.getCurrencyInstance(l);
+                break;
+            case INTEGER:
+                nf = NumberFormat.getIntegerInstance(l);
+                break;
+            case COMPACT:
+                nf = NumberFormat.getCompactNumberInstance(l, NumberFormat.Style.SHORT);
+                break;
+            case PERMILL:
+                nf = new DecimalFormat("#.#\u2030", DecimalFormatSymbols.getInstance(l));
+                break;
+        }
+
+        assertEquals(nf.format(SRC_NUM), expected);
+    }
+
+    @Test(dataProvider="charSymbols")
+    public void testCharSymbols(Locale l, char percent, char permill, char minus) {
+        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
+        assertEquals(dfs.getPercent(), percent);
+        assertEquals(dfs.getPerMill(), permill);
+        assertEquals(dfs.getMinusSign(), minus);
+    }
+
+    @Test
+    public void testSerialization() throws Exception {
+        DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance();
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        new ObjectOutputStream(bos).writeObject(dfs);
+        DecimalFormatSymbols dfsSerialized = (DecimalFormatSymbols)new ObjectInputStream(
+                new ByteArrayInputStream(bos.toByteArray())
+        ).readObject();
+
+        assertEquals(dfs, dfsSerialized);
+
+        // set minus/percent/permille
+        dfs.setMinusSign('a');
+        dfs.setPercent('b');
+        dfs.setPerMill('c');
+        bos = new ByteArrayOutputStream();
+        new ObjectOutputStream(bos).writeObject(dfs);
+        dfsSerialized = (DecimalFormatSymbols)new ObjectInputStream(
+                new ByteArrayInputStream(bos.toByteArray())
+        ).readObject();
+
+        assertEquals(dfs, dfsSerialized);
+    }
+}
--- a/test/jdk/java/util/Arrays/TimSortStackSize2.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/util/Arrays/TimSortStackSize2.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
  * @library /test/lib
  * @modules java.management
  *          java.base/jdk.internal
+ * @requires (vm.debug == false)
  * @build TimSortStackSize2
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
--- a/test/jdk/java/util/Locale/LocaleProviders.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/util/Locale/LocaleProviders.java	Tue Mar 26 09:05:10 2019 -0400
@@ -72,6 +72,10 @@
                 bug8027289Test(args[1]);
                 break;
 
+            case "bug8220227Test":
+                bug8220227Test();
+                break;
+
             default:
                 throw new RuntimeException("Test method '"+methodName+"' not found.");
         }
@@ -249,4 +253,15 @@
             }
         }
     }
+
+    static void bug8220227Test() {
+        if (System.getProperty("os.name").startsWith("Windows")) {
+            Locale l = new Locale("xx","XX");
+            String country = l.getDisplayCountry();
+            if (country.endsWith("(XX)")) {
+                throw new RuntimeException(
+                        "Unexpected Region name: " + country);
+            }
+        }
+    }
 }
--- a/test/jdk/java/util/Locale/LocaleProvidersRun.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/util/Locale/LocaleProvidersRun.java	Tue Mar 26 09:05:10 2019 -0400
@@ -25,7 +25,7 @@
  * @test
  * @bug 6336885 7196799 7197573 7198834 8000245 8000615 8001440 8008577
  *      8010666 8013086 8013233 8013903 8015960 8028771 8054482 8062006
- *      8150432 8215913
+ *      8150432 8215913 8220227
  * @summary tests for "java.locale.providers" system property
  * @library /test/lib
  * @build LocaleProviders
@@ -148,6 +148,12 @@
             testRun("COMPAT,HOST", "bug8027289Test", "FFE5", "", "");
             testRun("HOST", "bug8027289Test", "00A5", "", "");
         }
+
+        //testing 8220227 fix. (Windows only)
+        if (!defLang.equals("en")) {
+            testRun("HOST", "bug8220227Test", "", "", "");
+        }
+
     }
 
     private static void testRun(String prefList, String methodName,
--- a/test/jdk/java/util/Scanner/ScanTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/java/util/Scanner/ScanTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 4313885 4926319 4927634 5032610 5032622 5049968 5059533 6223711 6277261 6269946 6288823
- *      8072722 8139414 8166261
+ *      8072722 8139414 8166261 8172695
  * @summary Basic tests of java.util.Scanner methods
  * @key randomness
  * @modules jdk.localedata
@@ -49,26 +49,12 @@
     private static File inputFile = new File(System.getProperty("test.src", "."), "input.txt");
 
     public static void main(String[] args) throws Exception {
-
-        Locale reservedLocale = Locale.getDefault();
-        String lang = reservedLocale.getLanguage();
+        Locale defaultLocale = Locale.getDefault();
         try {
-            if (!"en".equals(lang) &&
-                !"zh".equals(lang) &&
-                !"ko".equals(lang) &&
-                !"ja".equals(lang)) {
-                //Before we have resource to improve the test to be ready for
-                //arbitrary locale, force the default locale to be "English"
-                //for now. First we check whether the "English" locale is
-                //available on the system as it could be absent due to varying
-                //configurations.
-                if (!Arrays.asList(Locale.getAvailableLocales())
-                    .contains(Locale.ENGLISH)) {
-                    throw new RuntimeException
-                       ("The \"English\" Locale is unavailable on this system");
-                }
-                Locale.setDefault(Locale.ENGLISH);
-            }
+            // Before we have resource to improve the test to be ready for
+            // arbitrary locale, force the default locale to be ROOT for now.
+            Locale.setDefault(Locale.US);
+
             skipTest();
             findInLineTest();
             findWithinHorizonTest();
@@ -128,7 +114,7 @@
                 System.err.println("OKAY: All tests passed.");
         } finally {
             // restore the default locale
-            Locale.setDefault(reservedLocale);
+            Locale.setDefault(defaultLocale);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/accessibility/6192422/bug6192422.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.SwingUtilities;
+
+/**
+ * @test
+ * @bug 6192422 7106851
+ * @key headful
+ * @summary Verifies fix for JMenuBar not being in the accessibility hierarchy
+ */
+public class bug6192422 {
+
+    private static boolean foundJMenuBar = false;
+
+    public static void main(String[] args) throws Throwable {
+        SwingUtilities.invokeAndWait(new Runnable() {
+            public void run() {
+                if (!testIt()) {
+                    throw new RuntimeException("JMenuBar was not found");
+                }
+            }
+        });
+    }
+
+    /*
+     * Test whether JMenuBar is in accessibility hierarchy
+     */
+    private static boolean testIt() {
+
+        JFrame frame = new JFrame("bug6192422");
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        /*
+         * Add a menu bar to the frame using setJMenuBar. The setJMenuBar
+         * method add the menu bar to the JLayeredPane.
+         */
+        JMenuBar menuBar = new JMenuBar();
+        menuBar.add(new JMenu("foo"));
+        menuBar.add(new JMenu("bar"));
+        menuBar.add(new JMenu("baz"));
+        frame.setJMenuBar(menuBar);
+
+        findJMenuBar(frame.getAccessibleContext());
+        return foundJMenuBar;
+    }
+
+    /*
+     * Finds the JMenuBar in the Accessibility hierarchy
+     */
+    private static void findJMenuBar(AccessibleContext ac) {
+        if (ac != null) {
+            System.err.println("findJMenuBar: ac = "+ac.getClass());
+            int num = ac.getAccessibleChildrenCount();
+            System.err.println("  #children "+num);
+
+            for (int i = 0; i < num; i++) {
+                System.err.println("  child #"+i);
+                Accessible a = ac.getAccessibleChild(i);
+                AccessibleContext child = a.getAccessibleContext();
+                AccessibleRole role = child.getAccessibleRole();
+                System.err.println("  role "+role);
+                if (role == AccessibleRole.MENU_BAR) {
+                    foundJMenuBar = true;
+                    return;
+                }
+                if (child.getAccessibleChildrenCount() > 0) {
+                    findJMenuBar(child);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/SecKeyFacSunJCEPrf.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8218723
+ * @summary Use SunJCE Mac in SecretKeyFactory PBKDF2 implementation
+ * @library evilprov.jar
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main/othervm SecKeyFacSunJCEPrf
+ */
+
+import java.util.Arrays;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.PBEKeySpec;
+import java.security.Provider;
+import java.security.Security;
+import com.evilprovider.*;
+import jdk.test.lib.Convert;
+
+public class SecKeyFacSunJCEPrf {
+
+    // One of the PBKDF2 HMAC-SHA1 test vectors from RFC 6070
+    private static final byte[] SALT = "salt".getBytes();
+    private static final char[] PASS = "password".toCharArray();
+    private static final int ITER = 4096;
+    private static final byte[] EXP_OUT = Convert.hexStringToByteArray(
+            "4B007901B765489ABEAD49D926F721D065A429C1");
+
+    public static void main(String[] args) throws Exception {
+        // Instantiate the Evil Provider and insert it in the
+        // most-preferred position.
+        Provider evilProv = new EvilProvider();
+        System.out.println("3rd Party Provider: " + evilProv);
+        Security.insertProviderAt(evilProv, 1);
+
+        SecretKeyFactory pbkdf2 =
+                SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1", "SunJCE");
+        PBEKeySpec pbks = new PBEKeySpec(PASS, SALT, ITER, 160);
+
+        SecretKey secKey1 = pbkdf2.generateSecret(pbks);
+        System.out.println("PBKDF2WithHmacSHA1:\n" +
+                    Convert.byteArrayToHexString(secKey1.getEncoded()));
+        if (Arrays.equals(secKey1.getEncoded(), EXP_OUT)) {
+            System.out.println("Test Vector Passed");
+        } else {
+            System.out.println("Test Vector Failed");
+            System.out.println("Expected Output:\n" +
+                    Convert.byteArrayToHexString(EXP_OUT));
+            throw new RuntimeException();
+        }
+    }
+}
+
Binary file test/jdk/javax/crypto/SecretKeyFactory/evilprov.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/Makefile	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,55 @@
+#
+# Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# Java paths
+#JAVA_BASE=PATH_TO_JAVA_IMG_DIR
+JAVABIN=$(JAVA_BASE)/bin
+JAVAC=$(JAVABIN)/javac
+JAVA=$(JAVABIN)/java
+JAR=$(JAVABIN)/jar 
+JARSIGNER=$(JAVABIN)/jarsigner
+
+# Compile-time flags and paths
+JFLAGS=-Xlint:all
+SRCPATH=com/evilprovider
+CLASSDST=classes
+
+PROVJAR=evilprov.jar
+KSTORE=PATH_TO_KEYSTORE
+KALIAS=PLACE_SIGNING_ALIAS_HERE
+MODVER=1.0
+
+all: $(PROVJAR)
+
+%.class: %.java
+	mkdir -p $(CLASSDST)
+	$(JAVAC) -d $(CLASSDST) $(JFLAGS) $<
+
+$(PROVJAR): $(SRCPATH)/EvilHmacSHA1.class $(SRCPATH)/EvilProvider.class module-info.class
+	$(JAR) --create --file $(PROVJAR) --module-version $(MODVER) -C $(CLASSDST) .
+
+signed: $(PROVJAR)
+	jarsigner -keystore $(KSTORE) $(PROVJAR).jar $(KALIAS)
+
+clean:
+	rm -rf $(CLASSDST) $(PROVJAR)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/README	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,15 @@
+Everything in this directory is dedicated to building the EvilProvider
+used with the SecKeyFacSunJCEPRF test (JDK-8218723).
+
+The makefile does require a JDK image path to be provided through the
+JAVA_BASE makefile variable.  As an example:
+
+make JAVA_BASE=/usr/java/jdk-11.0.1 evilprov
+
+Since the EvilProvider is a modular jar, JDK 9 or later should be used.
+
+For OpenJDK, no signing is required.  If signing is required (for use
+with Oracle JDK, for instance), you must obtain a JCE signing certificate
+and place it in a keystore, then run the "signed" makefile target (it will
+build the jar file if it does not already exist).
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/com/evilprovider/EvilHmacSHA1.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.evilprovider;
+
+import java.security.*;
+import java.security.spec.*;
+import java.nio.ByteBuffer;
+
+import javax.crypto.*;
+
+public final class EvilHmacSHA1 extends MacSpi {
+    private final Mac internalMac;
+
+    public EvilHmacSHA1() throws GeneralSecurityException {
+        internalMac = Mac.getInstance("HmacSHA1", "SunJCE");
+    }
+
+    @Override
+    protected byte[] engineDoFinal() {
+        return internalMac.doFinal();
+    }
+
+    @Override
+    protected int engineGetMacLength() {
+        return internalMac.getMacLength();
+    }
+
+    @Override
+    protected void engineInit(Key key, AlgorithmParameterSpec spec)
+            throws InvalidKeyException, InvalidAlgorithmParameterException {
+        SecretKey sKey;
+        if (key instanceof SecretKey) {
+            sKey = (SecretKey)key;
+        } else {
+            throw new IllegalArgumentException("Key must be a SecretKey");
+        }
+
+        byte[] sKeyEnc = sKey.getEncoded();
+        int keyBits = sKeyEnc.length * 8;
+        if (keyBits < 160) {
+            throw new IllegalArgumentException("Key must be at least 160 bits");
+        }
+
+        // Pass through to init
+        internalMac.init(key, spec);
+    }
+
+    @Override
+    protected void engineReset() {
+        internalMac.reset();
+    }
+
+    @Override
+    protected void engineUpdate(byte input) {
+        internalMac.update(input);
+    }
+
+    @Override
+    protected void engineUpdate(byte[] input, int offset, int len) {
+        internalMac.update(input, offset, len);
+    }
+
+    @Override
+    protected void engineUpdate(ByteBuffer input) {
+        internalMac.update(input);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/com/evilprovider/EvilProvider.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.evilprovider;
+
+import java.security.*;
+
+public final class EvilProvider extends Provider {
+
+    private static final long serialVersionUID = 11223344550000L;
+
+    public EvilProvider() {
+        super("EvilProvider", "1.0", "Evil Provider");
+        putService(new Provider.Service(this, "Mac", "HmacSHA1",
+                    "com.evilprovider.EvilHmacSHA1", null, null));
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/crypto/SecretKeyFactory/evilprov/module-info.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 the evil provider
+ *
+ * @provides java.security.Provider
+ *
+ * @moduleGraph
+ */
+module jdk.evilprovider {
+    provides java.security.Provider with com.evilprovider.EvilProvider;
+}
--- a/test/jdk/javax/imageio/AppletResourceTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-<!--
-  ~ Copyright (c) 2003, 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.
-  ~
-  ~ This code is distributed in the hope that it will be useful, but WITHOUT
-  ~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  ~ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-  ~ version 2 for more details (a copy is included in the LICENSE file that
-  ~ accompanied this code).
-  ~
-  ~ You should have received a copy of the GNU General Public License version
-  ~ 2 along with this work; if not, write to the Free Software Foundation,
-  ~ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-  ~
-  ~ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-  ~ or visit www.oracle.com if you need additional information or have any
-  ~ questions.
-  -->
-
-<html>
-<!--
- test
- @bug 4481957
- @run main AppletResourceTest
- @run applet RestrictedBundleTest.html
- @summary Tests that applet-supplied ImageReader, ImageWriter, and
- IIOMetadataFormat implementations do not throw unexpected exceptions
- when indirectly attempting to access ResourceBundles.
-  -->
-<head>
-<title> AppletResourceTest </title>
-</head>
-<body>
-<applet code=AppletResourceTest.class width=400 height=400></applet>
-</body>
-</html>
--- a/test/jdk/javax/imageio/AppletResourceTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/javax/imageio/AppletResourceTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, 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
@@ -24,15 +24,12 @@
 /*
  * @test
  * @bug 4481957
- * @key headful
  * @summary Tests that applet-supplied ImageReader, ImageWriter, and
  *          IIOMetadataFormat implementations do not throw unexpected exceptions
  *          when indirectly attempting to access ResourceBundles
  * @run main AppletResourceTest
- * @run applet AppletResourceTest.html
  */
 
-import java.applet.Applet;
 import java.awt.Rectangle;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
@@ -53,7 +50,7 @@
 
 import org.w3c.dom.Node;
 
-public class AppletResourceTest extends Applet {
+public class AppletResourceTest {
 
     public static void main(String[] argv) {
         new AppletResourceTest().init();
--- a/test/jdk/javax/swing/JFrame/4962534/bug4962534.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<html>
-<!--
-  Copyright (c) 2012, 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
-  @key headful
-  @bug 4962534
-  @summary JFrame dances very badly
-  @author dav@sparc.spb.su area=
-  @run applet bug4962534.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>bug4962534<br>Bug ID: 4962534 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="bug4962534.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/javax/swing/JFrame/4962534/bug4962534.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/javax/swing/JFrame/4962534/bug4962534.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,19 +22,19 @@
  */
 
 /*
- test
- @bug 4962534 7104594
- @summary JFrame dances very badly
- @author dav@sparc.spb.su area=
- @run applet bug4962534.html
+  @test
+  @key headful
+  @bug 4962534
+  @summary JFrame dances very badly
+  @run main bug4962534
  */
-import java.applet.Applet;
+
 import java.awt.*;
 import java.awt.event.*;
 import java.util.Random;
 import javax.swing.*;
 
-public class bug4962534 extends Applet {
+public class bug4962534 {
 
     Robot robot;
     volatile Point framePosition;
@@ -46,7 +46,12 @@
     volatile boolean titleFound = false;
     public static Object LOCK = new Object();
 
-    @Override
+    public static void main(final String[] args) {
+        bug4962534 app = new bug4962534();
+        app.init();
+        app.start();
+    }
+
     public void init() {
         try {
             SwingUtilities.invokeAndWait(new Runnable() {
@@ -60,10 +65,7 @@
         }
     }//End  init()
 
-    @Override
     public void start() {
-        validate();
-
         try {
             setJLayeredPaneEDT();
             setTitleComponentEDT();
@@ -149,6 +151,7 @@
         frame = new JFrame("JFrame Dance Test");
         frame.pack();
         frame.setSize(450, 260);
+        frame.setLocationRelativeTo(null);
         frame.setVisible(true);
     }
 
--- a/test/jdk/javax/swing/JPopupMenu/4634626/bug4634626.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<Html>
-<Body>
-<APPLET  code="bug4634626.class" WIDTH = 50 HEIGHT = 50>
-</APPLET>
-
-</Body>
-</Html>
-
--- a/test/jdk/javax/swing/JPopupMenu/4634626/bug4634626.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/javax/swing/JPopupMenu/4634626/bug4634626.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, 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
@@ -26,17 +26,16 @@
  * @key headful
  * @bug 4634626
  * @summary Implement context popup menus for components
- * @author Alexander Zuev
  * @library /lib/client
  * @build ExtendedRobot
- * @run applet bug4634626.html
+ * @run main bug4634626
  */
 
 import javax.swing.*;
 import java.awt.event.*;
 import java.awt.*;
 
-public class bug4634626 extends JApplet {
+public class bug4634626 {
 
     public boolean passed = true;
     public boolean done = false;
@@ -84,6 +83,12 @@
 
     public static MouseWatcher mouser = new MouseWatcher();
 
+    public static void main(final String[] args) {
+        bug4634626 app = new bug4634626();
+        app.init();
+        app.destroy();
+    }
+
     public void init() {
 
         try {
@@ -118,6 +123,7 @@
         mainFrame.setLocation(50, 50);
 
         mainFrame.addWindowListener(new TestStateListener());
+        mainFrame.setLocationRelativeTo(null);
         mainFrame.setVisible(true);
 
         while(!done) Thread.yield();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JTabbedPane/TabProb.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 8215396
+   @key headful
+   @summary Verifies JTabbedPane preferred size calculation is wrong
+   for SCROLL_TAB_LAYOUT.
+   @run main TabProb
+ */
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Color;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.LayoutManager;
+import java.awt.Insets;
+import java.awt.Robot;
+import javax.swing.BorderFactory;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+public class TabProb extends JFrame {
+    static TabProb tb1;
+    static TabProb tb2;
+    class FixLayout implements LayoutManager {
+        @Override
+        public void layoutContainer(Container C) {
+            Insets in = C.getInsets();
+            int w = 200 - in.left - in.right;
+            int h = 100 - in.top - in.bottom;
+            C.getComponents()[0].setBounds(in.top, in.left, w, h);
+        }
+        @Override
+        public Dimension minimumLayoutSize(Container C) {
+            return new Dimension(200, 100);
+        }
+        @Override
+        public Dimension preferredLayoutSize(Container C) {
+            return new Dimension(200, 100);
+        }
+        @Override
+        public void removeLayoutComponent(Component c) {
+        }
+        @Override
+        public void addLayoutComponent(String s, Component c) {
+        }
+    }
+
+    public TabProb(int layoutPolicy) {
+        JTabbedPane tabpanel = new JTabbedPane();
+        tabpanel.setTabPlacement(JTabbedPane.TOP);
+        tabpanel.setTabLayoutPolicy(layoutPolicy);
+        JPanel panel = new JPanel(new FixLayout());
+        JLabel label = new JLabel("Label");
+        label.setBorder(BorderFactory.createLineBorder(Color.green, 3));
+        panel.add(label);
+        tabpanel.add("TEST", panel);
+        add(tabpanel, BorderLayout.CENTER);
+        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+    }
+
+    public static void main(String[] args) throws Exception {
+        for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
+            System.out.println("Test for LookAndFeel " + laf.getClassName());
+            UIManager.setLookAndFeel(laf.getClassName());
+            test();
+            System.out.println("Test passed for LookAndFeel " + laf.getClassName());
+        }
+    }
+
+    public static void test() throws Exception {
+        Robot robot = new Robot();
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                tb1 = new TabProb(JTabbedPane.SCROLL_TAB_LAYOUT);
+                tb1.pack();
+                tb1.setVisible(true);
+
+                tb2 = new TabProb(JTabbedPane.WRAP_TAB_LAYOUT);
+                tb2.pack();
+                tb2.setVisible(true);
+            }
+        });
+        double tb1height = tb1.getPreferredSize().getHeight();
+        double tb2height = tb2.getPreferredSize().getHeight();
+        System.out.println(tb1height);
+        System.out.println(tb2height);
+
+        robot.waitForIdle();
+        robot.delay(2000);
+
+        SwingUtilities.invokeAndWait(() -> tb1.dispose());
+        SwingUtilities.invokeAndWait(() -> tb2.dispose());
+
+        if (tb1height != tb2height) {
+            throw new RuntimeException("JTabbedPane preferred size calculation is wrong for SCROLL_TAB_LAYOUT");
+        }
+    }
+}
--- a/test/jdk/javax/swing/MultiUIDefaults/4300666/bug4300666.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-<!--
- Copyright (c) 2007, 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.
--->
- 
-<html>
-<body>
-<applet  code="bug4300666.class" width=200 height=200></applet>
-</body>
-</html>
--- a/test/jdk/javax/swing/MultiUIDefaults/4300666/bug4300666.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/javax/swing/MultiUIDefaults/4300666/bug4300666.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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,19 +23,15 @@
 
 /*
  * @test
- * @key headful
  * @bug 4300666
  * @summary Printing UIDefaults throws NoSuchElementExcept
- * @author Andrey Pikalev
- * @run applet bug4300666.html
  */
 
 import javax.swing.*;
 
+public class bug4300666 {
 
-public class bug4300666 extends JApplet {
-
-    public void init() {
+    public static void main(final String[] args) {
         UIDefaults d = UIManager.getDefaults();
         d.toString();
     }
--- a/test/jdk/javax/swing/text/StyledEditorKit/4506788/bug4506788.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-<!--
- Copyright (c) 2012, 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.
--->
-
-<Html>
-<Body>
-<APPLET  code="bug4506788.class" WIDTH = 600 HEIGHT = 400></APPLET>
-</Body>
-</Html>
--- a/test/jdk/javax/swing/text/StyledEditorKit/4506788/bug4506788.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/javax/swing/text/StyledEditorKit/4506788/bug4506788.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,8 +26,7 @@
  * @key headful
  * @bug 4506788 7147408
  * @summary  Tests if cursor gets stuck after insertion a character
- * @author Denis Sharypov
- * @run applet bug4506788.html
+ * @run main bug4506788
  */
 
 import java.awt.*;
@@ -37,12 +36,17 @@
 import javax.swing.event.*;
 import javax.swing.text.*;
 
-public class bug4506788 extends JApplet {
+public class bug4506788 {
 
     private volatile boolean passed = false;
     private JEditorPane jep;
 
-    @Override
+    public static void main(final String[] args) {
+        bug4506788 app = new bug4506788();
+        app.init();
+        app.start();
+    }
+
     public void init() {
         try {
             SwingUtilities.invokeAndWait(new Runnable() {
@@ -57,7 +61,6 @@
         }
     }
 
-    @Override
     public void start() {
         Robot robot;
         try {
@@ -129,6 +132,7 @@
 
         f.getContentPane().add(jep);
         f.setSize(100, 100);
+        f.setLocationRelativeTo(null);
         f.setVisible(true);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/text/html/8218674/TooltipImageTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @key headful
+ * @bug 8218674
+ * @summary Tests if Images are rendered and scaled correctly in JToolTip.
+ * @run main TooltipImageTest
+ */
+import java.awt.Dimension;
+import java.awt.Insets;
+import javax.swing.JToolTip;
+import javax.swing.SwingUtilities;
+
+public class TooltipImageTest {
+
+    private static void checkSize(JToolTip tip, int width, int height) {
+        Dimension d = tip.getPreferredSize();
+        Insets insets = tip.getInsets();
+        //6 seems to be the extra width being allocated for some reason
+        //for a tooltip window.
+        if (!((d.width - insets.right - insets.left - 6) == width) &&
+            !((d.height - insets.top - insets.bottom) == height)) {
+            throw new RuntimeException("Test case fails: Expected width, height is " + width + ", " + height +
+                    " whereas actual width, height are " + (d.width - insets.right - insets.left - 6) + " " +
+                    (d.height - insets.top - insets.bottom));
+        }
+     }
+
+    public static void main(String[] args) throws Exception {
+        String PATH = TooltipImageTest.class.getResource("circle.png").getPath();
+        SwingUtilities.invokeAndWait(() -> {
+            JToolTip tip = new JToolTip();
+            tip.setTipText("<html><img width=\"100\" src=\"file:///" + PATH + "\"></html>");
+            checkSize(tip, 100, 100);
+
+            tip.setTipText("<html><img height=\"100\" src=\"file:///" + PATH + "\"></html>");
+            checkSize(tip, 100, 100);
+
+            tip.setTipText("<html><img src=\"file:///" + PATH + "\"></html>");
+            checkSize(tip, 200, 200);
+
+            tip.setTipText("<html><img width=\"50\" src=\"file:///" + PATH + "\"></html>");
+            checkSize(tip, 50, 50);
+
+            tip.setTipText("<html><img height=\"50\" src=\"file:///" + PATH + "\"></html>");
+            checkSize(tip, 50, 50);
+
+            tip.setTipText("<html><img width=\"100\" height=\"50\" src=\"file:///" + PATH + "\"></html>");
+            checkSize(tip, 100, 50);
+        });
+
+        System.out.println("Test case passed.");
+    }
+}
Binary file test/jdk/javax/swing/text/html/8218674/circle.png has changed
--- a/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java	Tue Mar 26 09:05:10 2019 -0400
@@ -64,10 +64,15 @@
         long count = Metrics.systemMetrics().getMemoryFailCount();
 
         // Allocate 512M of data
-        long[][] longs = new long[64][];
-        for (int i = 1; i <= 64; i++) {
+        byte[][] bytes = new byte[64][];
+        for (int i = 0; i < 64; i++) {
             try {
-                longs[i] = new long[8 * 1024 * 1024];
+                bytes[i] = new byte[8 * 1024 * 1024];
+                // Break out as soon as we see an increase in failcount
+                // to avoid getting killed by the OOM killer.
+                if (Metrics.systemMetrics().getMemoryFailCount() > count) {
+                    break;
+                }
             } catch (Error e) { // OOM error
                 break;
             }
--- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java	Tue Mar 26 09:05:10 2019 -0400
@@ -90,6 +90,7 @@
                 new DockerRunOptions(imageName, "/jdk/bin/java", "MetricsMemoryTester");
         opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/")
                 .addDockerOpts("--memory=" + value)
+                .addJavaOpts("-Xmx" + value)
                 .addJavaOpts("-cp", "/test-classes/")
                 .addJavaOpts("--add-exports", "java.base/jdk.internal.platform=ALL-UNNAMED")
                 .addClassOptions("failcount");
--- a/test/jdk/jdk/jfr/event/io/TestInstrumentation.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/jdk/jfr/event/io/TestInstrumentation.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -105,14 +105,14 @@
         "java/io/FileOutputStream::write::(I)V",
         "java/io/FileOutputStream::write::([B)V",
         "java/io/FileOutputStream::write::([BII)V",
-        "java/net/SocketInputStream::read::()I",
-        "java/net/SocketInputStream::read::([B)I",
-        "java/net/SocketInputStream::read::([BII)I",
-        "java/net/SocketInputStream::close::()V",
-        "java/net/SocketOutputStream::write::(I)V",
-        "java/net/SocketOutputStream::write::([B)V",
-        "java/net/SocketOutputStream::write::([BII)V",
-        "java/net/SocketOutputStream::close::()V",
+        "java/net/Socket$SocketInputStream::read::()I",
+        "java/net/Socket$SocketInputStream::read::([B)I",
+        "java/net/Socket$SocketInputStream::read::([BII)I",
+        "java/net/Socket$SocketInputStream::close::()V",
+        "java/net/Socket$SocketOutputStream::write::(I)V",
+        "java/net/Socket$SocketOutputStream::write::([B)V",
+        "java/net/Socket$SocketOutputStream::write::([BII)V",
+        "java/net/Socket$SocketOutputStream::close::()V",
         "java/nio/channels/FileChannel::read::([Ljava/nio/ByteBuffer;)J",
         "java/nio/channels/FileChannel::write::([Ljava/nio/ByteBuffer;)J",
         "java/nio/channels/SocketChannel::open::()Ljava/nio/channels/SocketChannel;",
--- a/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/jdk/jfr/jvm/TestDumpOnCrash.java	Tue Mar 26 09:05:10 2019 -0400
@@ -77,22 +77,25 @@
     }
 
     public static void main(String[] args) throws Exception {
-        verify(runProcess(CrasherIllegalAccess.class.getName(), ""));
-        verify(runProcess(CrasherHalt.class.getName(), ""));
+        verify(runProcess(CrasherIllegalAccess.class.getName(), "", true));
+        verify(runProcess(CrasherIllegalAccess.class.getName(), "", false));
+        verify(runProcess(CrasherHalt.class.getName(), "", true));
+        verify(runProcess(CrasherHalt.class.getName(), "", false));
 
         // Verification is excluded for the test case below until 8219680 is fixed
-        long pid = runProcess(CrasherSig.class.getName(), "FPE");
+        long pid = runProcess(CrasherSig.class.getName(), "FPE", true);
         // @ignore 8219680
         // verify(pid);
     }
 
-    private static long runProcess(String crasher, String signal) throws Exception {
+    private static long runProcess(String crasher, String signal, boolean disk) throws Exception {
         System.out.println("Test case for crasher " + crasher);
+        final String flightRecordingOptions = "dumponexit=true,disk=" + Boolean.toString(disk);
         Process p = ProcessTools.createJavaProcessBuilder(true,
                 "-Xmx64m",
                 "-XX:-CreateCoredumpOnCrash",
                 "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
-                "-XX:StartFlightRecording",
+                "-XX:StartFlightRecording=" + flightRecordingOptions,
                 crasher,
                 signal)
             .start();
--- a/test/jdk/jdk/jfr/tool/TestPrint.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/jdk/jfr/tool/TestPrint.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
         output.shouldContain("missing file");
 
         output = ExecuteHelper.jfr("print", "missing.jfr");
-        output.shouldContain("could not find file ");
+        output.shouldContain("could not open file ");
 
         Path file = Utils.createTempFile("faked-print-file",  ".jfr");
         FileWriter fw = new FileWriter(file.toFile());
--- a/test/jdk/sanity/client/README	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/README	Tue Mar 26 09:05:10 2019 -0400
@@ -8,7 +8,7 @@
 1) Download/Install the JDK to be tested in the system.
    (For example C:/java/jdk1.9.0 in windows or 
     /export/jdk/jdk1.9.0 in linux/mac/solaris)
-2) Download/Install JTReg harness, minimum required version is 4.1 b13.    
+2) Download/Install JTReg harness.    
 3) Open terminal(cmd in windows, *not* cygwin) and go to the this directory.
 4) To run
     - see the notes below on how to prepare for the test run
@@ -42,4 +42,4 @@
 Jemmy and SwingSet3 sources are available as copies in lib folder.
 
 Original Jemmy repository is https://jemmy.java.net
-Original SwingSet3 repository is https://java.net/projects/swingset3
\ No newline at end of file
+Original SwingSet3 repository is https://java.net/projects/swingset3
--- a/test/jdk/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -42,7 +42,7 @@
 
 /*
  * @test
- * @key headful screenshots intermittent
+ * @key headful screenshots
  * @summary Verifies buttons on SwingSet3 ButtonDemo page by clicking each
  *          button, taking its screenshots and checking that pressed button
  *          image is different from initial button image.
--- a/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -51,7 +51,7 @@
 
 /*
  * @test
- * @key headful
+ * @key headful screenshots
  * @summary Verifies SwingSet3 EditorPaneDemo by navigating and and validating
  *  the page contents in all pages
  *
--- a/test/jdk/sanity/client/SwingSet/src/FileChooserDemoTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/SwingSet/src/FileChooserDemoTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,7 @@
 import org.netbeans.jemmy.operators.JDialogOperator;
 import org.netbeans.jemmy.operators.JComponentOperator.JComponentByTipFinder;
 import org.netbeans.jemmy.util.Platform;
+import org.netbeans.jemmy.util.LookAndFeel;
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Listeners;
 import org.jemmy2ext.JemmyExt.ByToolTipChooser;
@@ -141,9 +142,7 @@
         fileChooser = new JFileChooserOperator(JFileChooserOperator.findJFileChooser((Container) frame.getSource()));
         // In Aqua, GTK and Motif L&Fs, JFileChooser does not have
         // "Go Home", "Up One Level", "Get Details", "Get List" buttons.
-        if (!UIManager.getLookAndFeel().getID().equals("Aqua")
-                && !UIManager.getLookAndFeel().getID().equals("Motif")
-                && !UIManager.getLookAndFeel().getID().equals("GTK")) {
+        if (!LookAndFeel.isAqua() && !LookAndFeel.isMotif() && !LookAndFeel.isGTK()) {
             File previousDirectory = fileChooser.getCurrentDirectory();
             fileChooser.goHome();
             // In Windows, pressing goHome navigates to Desktop inside the home directory.
@@ -157,7 +156,7 @@
             fileChooser.rescanCurrentDirectory();
             // In Windows and Windows Classic L&F, List and Details views are
             // implemented as a popup menu item
-            if(UIManager.getLookAndFeel().getID().equals("Windows")) {
+            if(LookAndFeel.isWindows() || LookAndFeel.isWindowsClassic()) {
                 JButtonOperator popupButton = new JButtonOperator(fileChooser, new JComponentByTipFinder(
                         UIManager.getString("FileChooser.viewMenuButtonToolTipText", fileChooser.getLocale())));
                 popupButton.push();
@@ -274,8 +273,7 @@
         fileChooserDialog = new JDialogOperator(OPEN);
         String openButtonText = OPEN;
         // In GTK and Motif L&F, open button text is 'OK'
-        if (UIManager.getLookAndFeel().getID().equals("Motif")
-                || UIManager.getLookAndFeel().getID().equals("GTK")) {
+        if (LookAndFeel.isMotif() || LookAndFeel.isGTK()) {
             openButtonText = OK;
         }
         openButton = new JButtonOperator(fileChooser, openButtonText);
--- a/test/jdk/sanity/client/SwingSet/src/SliderDemoTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/SwingSet/src/SliderDemoTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -36,6 +36,8 @@
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JSliderOperator;
 import org.netbeans.jemmy.accessibility.AccessibleNameChooser;
+import org.netbeans.jemmy.util.LookAndFeel;
+
 import static com.sun.swingset3.demos.slider.SliderDemo.*;
 import org.testng.annotations.Listeners;
 
@@ -65,12 +67,10 @@
     private static final int HORIZONTAL_MINOR_TICKS_SLIDER_MAXIMUM = 11;
     private static final int VERTICAL_MINOR_TICKS_SLIDER_MINIMUM = 0;
     private static final int VERTICAL_MINOR_TICKS_SLIDER_MAXIMUM = 100;
-    private String currentLookAndFeel;
 
     @Test(dataProvider = "availableLookAndFeels", dataProviderClass = TestHelpers.class)
     public void test(String lookAndFeel) throws Exception {
         UIManager.setLookAndFeel(lookAndFeel);
-        currentLookAndFeel = lookAndFeel;
         new ClassReference(SliderDemo.class.getCanonicalName()).startApplication();
         JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
         plain(frame, HORIZONTAL_PLAIN_SLIDER);
@@ -148,7 +148,7 @@
     }
 
     private void checkKeyboard(JSliderOperator jso) {
-        boolean isMotif = currentLookAndFeel.equals("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
+        boolean isMotif = LookAndFeel.isMotif();
         checkKeyPress(jso, KeyEvent.VK_HOME,
                 jSlider -> jSlider.getValue() == jso.getMinimum());
 
--- a/test/jdk/sanity/client/SwingSet/src/SplitPaneDemoTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/SwingSet/src/SplitPaneDemoTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,7 @@
 import org.netbeans.jemmy.operators.JRadioButtonOperator;
 import org.netbeans.jemmy.operators.JSplitPaneOperator;
 import org.netbeans.jemmy.operators.JTextFieldOperator;
+import org.netbeans.jemmy.util.LookAndFeel;
 
 import org.testng.annotations.Listeners;
 import org.testng.annotations.Test;
@@ -76,7 +77,7 @@
         JSplitPaneOperator splitPane = new JSplitPaneOperator(frame);
 
         // OneTouch feature is not available in GTK L&F
-        if(!"GTK".equals(UIManager.getLookAndFeel().getID())) {
+        if(!LookAndFeel.isGTK()) {
             // Toggle OneTouch Expandable
             checkOneTouch(frame, splitPane, true);
             checkOneTouch(frame, splitPane, false);
@@ -89,7 +90,7 @@
 
         // TODO Skipping this code for Motif L&F as the fix for "CODETOOLS-7902324"
         // is deferred now
-        if(!("Motif".equals(UIManager.getLookAndFeel().getID()))) {
+        if(!LookAndFeel.isMotif()) {
             // Check moving the divider
             checkDividerMoves(frame, splitPane, false);
             checkDividerMoves(frame, splitPane, true);
--- a/test/jdk/sanity/client/SwingSet/src/SwingSet2DemoTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/SwingSet/src/SwingSet2DemoTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -34,6 +34,7 @@
 import org.netbeans.jemmy.ClassReference;
 import org.netbeans.jemmy.ComponentChooser;
 import org.netbeans.jemmy.TimeoutExpiredException;
+import org.netbeans.jemmy.Timeouts;
 import org.netbeans.jemmy.operators.ComponentOperator;
 import org.netbeans.jemmy.operators.JButtonOperator;
 import org.netbeans.jemmy.operators.JCheckBoxMenuItemOperator;
@@ -67,6 +68,7 @@
     private static final String OCEAN_THEME_NAME = "Ocean";
     private static final String STEEL_THEME_NAME = "Steel";
     private static final int TOOLTIP_DISMISS_DELAY = 60000;
+    private final static long TOOLTIP_TIMEOUT = 5000;
 
     /**
      * Testing check box menu item, radio button menu item, nested menus and
@@ -157,6 +159,8 @@
         // tooltip is showing for demo toggle button
         toolTipMenuItem.push();
         toolTipMenuItem.waitSelected(false);
+        // Set tooltip timeout as 5 seconds
+        testComp.getTimeouts().setTimeout("JToolTipOperator.WaitToolTipTimeout", TOOLTIP_TIMEOUT);
         boolean isToolTipTimeout = false;
         try {
             testComp.showToolTip();
--- a/test/jdk/sanity/client/TEST.ROOT.template	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-# This file identifies the root of the test-suite hierarchy.
-# It also contains test-suite configuration information.
-
-# The list of keywords supported in the entire test suite.  The
-# "intermittent" keyword marks tests known to fail intermittently.
-# The "randomness" keyword marks tests using randomness with test
-# cases differing from run to run. (A test using a fixed random seed
-# would not count as "randomness" by this definition.) Extra care
-# should be taken to handle test failures of intermittent or
-# randomness tests.
-#
-# A "headful" test requires a graphical environment to meaningfully
-# run. Tests that are not headful are "headless." 
-
-keys=2d dnd i18n intermittent randomness headful
-
-# Tests that must run in othervm mode
-othervm.dirs=sanity/client/SwingSet
-
-# Tests that cannot run concurrently
-exclusiveAccess.dirs=sanity/client/SwingSet
-
-# Tests using jtreg 4.1 b13 features
-requiredVersion=4.1 b13
--- a/test/jdk/sanity/client/TEST.properties	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/TEST.properties	Tue Mar 26 09:05:10 2019 -0400
@@ -1,3 +1,25 @@
+#  Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+#  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+#  This code is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License version 2 only, as
+#  published by the Free Software Foundation.
+#
+#  This code is distributed in the hope that it will be useful, but WITHOUT
+#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+#  version 2 for more details (a copy is included in the LICENSE file that
+#  accompanied this code).
+#
+#  You should have received a copy of the GNU General Public License version
+#  2 along with this work; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+#  Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+#  or visit www.oracle.com if you need additional information or have any
+#  questions.
+#
+
 # This file contains test-suite configuration information related to this portion
 # of the test suite.
 #
@@ -6,9 +28,3 @@
 
 # The list of keywords supported in this part of the test suite
 keys=screenshots
-
-# Tests that cannot run concurrently
-exclusiveAccess.dirs=SwingSet
-
-# Tests require jtreg 4.1 b13 features
-#requiredVersion=4.1 b13
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DefaultDriverInstaller.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/drivers/DefaultDriverInstaller.java	Tue Mar 26 09:05:10 2019 -0400
@@ -53,6 +53,7 @@
 import org.netbeans.jemmy.drivers.windows.DefaultInternalFrameDriver;
 import org.netbeans.jemmy.drivers.windows.DefaultWindowDriver;
 import org.netbeans.jemmy.drivers.windows.InternalFramePopupMenuDriver;
+import org.netbeans.jemmy.util.LookAndFeel;
 
 /**
  * Installs all necessary drivers for Jemmy operators except low-level drivers
@@ -122,9 +123,9 @@
                     new ChoiceDriver(),
                     new DefaultFrameDriver(),
                     new DefaultWindowDriver(),
-                    "Motif".equals(UIManager.getLookAndFeel().getID())? new InternalFramePopupMenuDriver(): new DefaultInternalFrameDriver(),
-                    "Motif".equals(UIManager.getLookAndFeel().getID())? new InternalFramePopupMenuDriver(): new DefaultInternalFrameDriver(),
-                    "Motif".equals(UIManager.getLookAndFeel().getID())? new InternalFramePopupMenuDriver(): new DefaultInternalFrameDriver(),
+                    LookAndFeel.isMotif()? new InternalFramePopupMenuDriver(): new DefaultInternalFrameDriver(),
+                    LookAndFeel.isMotif()? new InternalFramePopupMenuDriver(): new DefaultInternalFrameDriver(),
+                    LookAndFeel.isMotif()? new InternalFramePopupMenuDriver(): new DefaultInternalFrameDriver(),
                     new APIFocusDriver(),
                     new MouseFocusDriver(),
                     (shortcutEvents ? new QueueJMenuDriver() : new DefaultJMenuDriver()),
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JFileChooserOperator.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JFileChooserOperator.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,6 @@
 import javax.swing.JTextField;
 import javax.swing.JToggleButton;
 import javax.swing.ListModel;
-import javax.swing.UIManager;
 import javax.swing.filechooser.FileFilter;
 import javax.swing.filechooser.FileSystemView;
 import javax.swing.filechooser.FileView;
@@ -60,6 +59,7 @@
 import org.netbeans.jemmy.Timeouts;
 import org.netbeans.jemmy.Waitable;
 import org.netbeans.jemmy.Waiter;
+import org.netbeans.jemmy.util.LookAndFeel;
 
 /**
  *
@@ -344,8 +344,7 @@
         int index = 0;
         // In GTK and Motif L&F, there are two JLists, one is to list folders
         // and second one one is to list files
-        if (UIManager.getLookAndFeel().getID().equals("Motif")
-                || UIManager.getLookAndFeel().getID().equals("GTK")) {
+        if (LookAndFeel.isMotif() || LookAndFeel.isGTK()) {
             index =1;
         }
         return innerSearcher.
@@ -445,7 +444,7 @@
         // In Windows and Windows Classic L&F, there is no 'Go Home' button,
         // but there is a toggle button to go desktop. In Windows platform
         // 'Go Home' button usually navigates to Desktop only.
-        if(UIManager.getLookAndFeel().getID().equals("Windows")) {
+        if(LookAndFeel.isWindows() || LookAndFeel.isWindowsClassic()) {
             homeOper =new JToggleButtonOperator(this, 1);
         } else {
             homeOper = new JButtonOperator(getHomeButton());
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JInternalFrameOperator.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JInternalFrameOperator.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,7 @@
 import org.netbeans.jemmy.drivers.InternalFrameDriver;
 import org.netbeans.jemmy.drivers.WindowDriver;
 import org.netbeans.jemmy.util.EmptyVisualizer;
+import org.netbeans.jemmy.util.LookAndFeel;
 import org.netbeans.jemmy.util.Platform;
 
 /**
@@ -1419,7 +1420,7 @@
                         return "JInternalFrameOperator.initOperators.ComponentChooser{description = " + getDescription() + '}';
                     }
                 }) != null) {
-                    if("Motif".equals(UIManager.getLookAndFeel().getID())) {
+                    if(LookAndFeel.isMotif()) {
                         popupButtonOper = new JButtonOperator(titleOperator, 0);
                     } else {
                         minOper = new JButtonOperator(titleOperator,
@@ -1436,7 +1437,7 @@
                     maxOper = null;
                 }
                 if (isClosable()) {
-                    if(!"Motif".equals(UIManager.getLookAndFeel().getID())) {
+                    if(!LookAndFeel.isMotif()) {
                         closeOper = new JButtonOperator(titleOperator,
                             new JComponentByTipFinder(CLOSE_BUTTON_TOOLTIP));
                     }
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JToolTipOperator.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JToolTipOperator.java	Tue Mar 26 09:05:10 2019 -0400
@@ -37,8 +37,11 @@
 
 import org.netbeans.jemmy.ComponentChooser;
 import org.netbeans.jemmy.ComponentSearcher;
+import org.netbeans.jemmy.JemmyException;
 import org.netbeans.jemmy.TimeoutExpiredException;
+import org.netbeans.jemmy.Timeouts;
 import org.netbeans.jemmy.Waitable;
+import org.netbeans.jemmy.Waiter;
 
 /**
  * <BR>
@@ -52,6 +55,8 @@
  */
 public class JToolTipOperator extends JComponentOperator {
 
+    private static long WAIT_TOOLTIP_TIMEOUT = 60000;
+
     /**
      * Identifier for a "tip text" property.
      *
@@ -59,6 +64,9 @@
      */
     public static final String TIP_TEXT_DPROP = "TipText";
 
+    static {
+        Timeouts.initDefault("JToolTipOperator.WaitToolTipTimeout", WAIT_TOOLTIP_TIMEOUT);
+    }
     /**
      * Constructs a JToolTipOperator object, waiting for a shown
      * JToolTip.
@@ -286,8 +294,7 @@
      */
     public static JToolTip waitJToolTip(ComponentOperator comp,
             ComponentChooser chooser) {
-        return Operator.getEnvironmentOperator().
-                waitState(new Waitable<JToolTip, Void>() {
+        Waitable<JToolTip, Void> waitable = new Waitable<JToolTip, Void>() {
             @Override
             public JToolTip actionProduced(Void obj) {
                 return findJToolTip(comp, chooser);
@@ -304,7 +311,19 @@
                 return "JToolTipOperator.waitJToolTip.Waitable{description = "
                         + getDescription() + '}';
             }
-        });
+        };
+        Waiter<JToolTip, Void> stateWaiter = new Waiter<>(waitable);
+        stateWaiter.setTimeoutsToCloneOf(Operator.getEnvironmentOperator().
+                getTimeouts(), "JToolTipOperator.WaitToolTipTimeout");
+        stateWaiter.setOutput(Operator.getEnvironmentOperator().
+                getOutput().createErrorOutput());
+        try {
+            return stateWaiter.waitAction(null);
+        } catch (InterruptedException e) {
+           Thread.currentThread().interrupt();
+           throw (new JemmyException("Waiting of " + waitable.getDescription()
+               + " state has been interrupted!"));
+        }
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/util/LookAndFeel.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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.netbeans.jemmy.util;
+
+import javax.swing.UIManager;
+
+/**
+ * Class to provide look and feel related utility APIs
+ */
+public class LookAndFeel {
+
+    /**
+     * Checking whether the current look and feel is Metal L&F
+     *
+     * @return returns true if current look and feel is Metal L&F,
+     *         otherwise false
+     */
+    public static boolean isMetal() {
+        return isLookAndFeel("Metal");
+    }
+
+    /**
+     * Checking whether the current look and feel is Nimbus L&F
+     *
+     * @return returns true if current look and feel is Nimbus L&F,
+     *         otherwise false
+     */
+    public static boolean isNimbus() {
+        return isLookAndFeel("Nimbus");
+    }
+
+    /**
+     * Checking whether the current look and feel is Motif L&F
+     *
+     * @return returns true if current look and feel is Motif L&F,
+     *         otherwise false
+     */
+    public static boolean isMotif() {
+        return isLookAndFeel("Motif");
+    }
+
+    /**
+     * Checking whether the current look and feel is GTK L&F
+     *
+     * @return returns true if current look and feel is GTK L&F,
+     *         otherwise false
+     */
+    public static boolean isGTK() {
+        return isLookAndFeel("GTK");
+    }
+
+    /**
+     * Checking whether the current look and feel is Aqua L&F
+     *
+     * @return returns true if current look and feel is Aqua L&F,
+     *         otherwise false
+     */
+    public static boolean isAqua() {
+        return isLookAndFeel("Aqua");
+    }
+
+    /**
+     * Checking whether the current look and feel is Windows L&F
+     *
+     * @return returns true if current look and feel is Windows L&F,
+     *         otherwise false
+     */
+    public static boolean isWindows() {
+        return UIManager.getLookAndFeel().getClass().
+                getSimpleName().equals("WindowsLookAndFeel");
+    }
+
+    /**
+     * Checking whether the current look and feel is WindowsClassic L&F
+     *
+     * @return returns true if current look and feel is WindowsClassic L&F,
+     *         otherwise false
+     */
+    public static boolean isWindowsClassic() {
+        return UIManager.getLookAndFeel().getClass().
+                getSimpleName().equals("WindowsClassicLookAndFeel");
+    }
+
+    private static boolean isLookAndFeel(String id) {
+        return UIManager.getLookAndFeel().getID().equals(id);
+    }
+}
--- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/version_info	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/version_info	Tue Mar 26 09:05:10 2019 -0400
@@ -1,6 +1,6 @@
 Manifest-version: 1.0
 Main-Class: org.netbeans.jemmy.JemmyProperties
 Jemmy-MajorVersion: 3.0
-Jemmy-MinorVersion: 6.0
+Jemmy-MinorVersion: 8.0
 Jemmy-Build: @BUILD_NUMBER@
 
--- a/test/jdk/sun/java2d/cmm/ColorConvertOp/ConstructorsNullTest/ConstructorsNullTest.html	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-<!--
- Copyright (c) 2000, 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.
--->
-
-<html>
-<!--  
-  @test
-  @key headful
-  @bug 4185854
-  @summary Checks that constructors do not accept nulls and throw NPE
-  @author tdv@eng.sun.com: area= 
-  @run applet ConstructorsNullTest.html
-  -->
-<head>
-<title>  </title>
-</head>
-<body>
-
-<h1>ConstructorsNullTest<br>Bug ID: 4185854</h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="ConstructorsNullTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/test/jdk/sun/java2d/cmm/ColorConvertOp/ConstructorsNullTest/ConstructorsNullTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/java2d/cmm/ColorConvertOp/ConstructorsNullTest/ConstructorsNullTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -20,69 +20,22 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 /*
-  test
+  @test
   @bug 4185854
   @summary Checks that constructors do not accept nulls and throw NPE
-  @run applet ConstructorsNullTest.html
+  @run main ConstructorsNullTest
 */
 
-// Note there is no @ in front of test above.  This is so that the
-//  harness will not mistake this file as a test file.  It should
-//  only see the html file as a test file. (the harness runs all
-//  valid test files, so it would run this test twice if this file
-//  were valid as well as the html file.)
-// Also, note the area= after Your Name in the author tag.  Here, you
-//  should put which functional area the test falls in.  See the
-//  AWT-core home page -> test areas and/or -> AWT team  for a list of
-//  areas.
-// Note also the 'ConstructorsNullTest.html' in the run tag.  This should
-//  be changed to the name of the test.
-
-
-/**
- * ConstructorsNullTest.java
- *
- * summary:
- */
-
-import java.applet.Applet;
-import java.awt.*;
-import java.awt.image.*;
-import java.awt.color.*;
-
+import java.awt.RenderingHints;
+import java.awt.color.ColorSpace;
+import java.awt.color.ICC_Profile;
+import java.awt.image.ColorConvertOp;
 
-//Automated tests should run as applet tests if possible because they
-// get their environments cleaned up, including AWT threads, any
-// test created threads, and any system resources used by the test
-// such as file descriptors.  (This is normally not a problem as
-// main tests usually run in a separate VM, however on some platforms
-// such as the Mac, separate VMs are not possible and non-applet
-// tests will cause problems).  Also, you don't have to worry about
-// synchronisation stuff in Applet tests they way you do in main
-// tests...
-
-
-public class ConstructorsNullTest extends Applet
- {
-   //Declare things used in the test, like buttons and labels here
+public class ConstructorsNullTest {
 
-   public void init()
-    {
-      //Create instructions for the user here, as well as set up
-      // the environment -- set the layout manager, add buttons,
-      // etc.
-
-      this.setLayout (new BorderLayout ());
-
-    }//End  init()
-
-   public void start ()
-    {
-      //Get things going.  Request focus, set size, et cetera
-      setSize (200,200);
-      show();
-
+    public static void main(final String[] args) {
       ColorConvertOp gp;
       boolean passed = false;
       try {
@@ -104,12 +57,5 @@
           throw new RuntimeException("Test FAILED: one of constructors didn't throw NullPointerException.");
       }
       System.out.println("Test PASSED: all constructors threw NullPointerException.");
-
-      //What would normally go into main() will probably go here.
-      //Use System.out.println for diagnostic messages that you want
-      //to read after the test is done.
-      //Use System.out.println for messages you want the tester to read.
-
-    }// start()
-
- }// class ConstructorsNullTest
+    }
+}// class ConstructorsNullTest
--- a/test/jdk/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/management/jmxremote/bootstrap/JMXAgentInterfaceBinding.java	Tue Mar 26 09:05:10 2019 -0400
@@ -28,10 +28,13 @@
 import java.net.Socket;
 import java.net.SocketAddress;
 import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import javax.management.remote.JMXConnector;
 import javax.management.remote.JMXConnectorFactory;
@@ -135,9 +138,9 @@
         private final int rmiPort;
         private final boolean useSSL;
         private final CountDownLatch latch;
-        private boolean failed;
-        private boolean jmxConnectWorked;
-        private boolean rmiConnectWorked;
+        private volatile boolean failed;
+        private volatile boolean jmxConnectWorked;
+        private volatile boolean rmiConnectWorked;
 
         private JMXConnectorThread(String addr,
                                    int jmxPort,
@@ -156,6 +159,7 @@
             try {
                 connect();
             } catch (IOException e) {
+                e.printStackTrace();
                 failed = true;
             }
         }
@@ -223,14 +227,16 @@
 
     private static class MainThread extends Thread {
 
-        private static final int WAIT_FOR_JMX_AGENT_TIMEOUT_MS = 500;
+        private static final String EXP_TERM_MSG_REG = "Exit: ([0-9]+)";
+        private static final Pattern EXIT_PATTERN = Pattern.compile(EXP_TERM_MSG_REG);
+        private static final String COOP_EXIT = "MainThread: Cooperative Exit";
+        private static final int WAIT_FOR_JMX_AGENT_TIMEOUT_MS = 20_000;
         private final String addr;
         private final int jmxPort;
         private final int rmiPort;
         private final boolean useSSL;
-        private boolean terminated = false;
         private boolean jmxAgentStarted = false;
-        private Exception excptn;
+        private volatile Exception excptn;
 
         private MainThread(InetAddress bindAddress, int jmxPort, int rmiPort, boolean useSSL) {
             this.addr = wrapAddress(bindAddress.getHostAddress());
@@ -243,14 +249,16 @@
         public void run() {
             try {
                 waitUntilReadyForConnections();
-                // Do nothing, but wait for termination.
-                try {
-                    while (!terminated) {
-                        Thread.sleep(100);
-                    }
-                } catch (InterruptedException e) { // ignore
+
+                // Wait for termination message
+                String actualTerm = new String(System.in.readAllBytes(), StandardCharsets.UTF_8).trim();
+                System.err.println("DEBUG: MainThread: actualTerm: '" + actualTerm + "'");
+                Matcher matcher = EXIT_PATTERN.matcher(actualTerm);
+                if (matcher.matches()) {
+                    int expExitCode = Integer.parseInt(matcher.group(1));
+                    System.out.println(COOP_EXIT);
+                    System.exit(expExitCode); // The main test expects this exit value
                 }
-                System.out.println("MainThread: Thread stopped.");
             } catch (Exception e) {
                 this.excptn = e;
             }
--- a/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/management/jmxremote/bootstrap/JMXInterfaceBindingTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -24,6 +24,7 @@
 import java.io.File;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
+import java.net.UnknownHostException;
 import java.net.SocketException;
 import java.util.ArrayList;
 import java.util.List;
@@ -33,33 +34,32 @@
 import jdk.test.lib.process.ProcessTools;
 
 /**
- * NOTE:
- *    This test requires at least a setup similar to the following in
- *    /etc/hosts file (or the windows equivalent). I.e. it expects it to
- *    be multi-homed and not both being the loop-back interface.
- *    For example:
- *    ----->8-------- /etc/hosts ----------->8---
- *    127.0.0.1   localhost
- *    192.168.0.1 localhost
- *    ----->8-------- /etc/hosts ----------->8---
- *
  * @test
  * @bug     6425769
  * @summary Test JMX agent host address binding. Same ports but different
- *          interfaces to bind to (using plain sockets and SSL sockets).
+ *          interfaces to bind to (selecting plain or SSL sockets at random
+ * @key intermittent
  *
  * @library /test/lib
  * @modules java.management.rmi
  *
  * @build JMXAgentInterfaceBinding
- * @run main/timeout=5 JMXInterfaceBindingTest
+ * @run main/timeout=60 JMXInterfaceBindingTest
  */
 public class JMXInterfaceBindingTest {
 
     public static final int COMMUNICATION_ERROR_EXIT_VAL = 1;
-    public static final int STOP_PROCESS_EXIT_VAL = 143;
-    public static final int JMX_PORT = 9111;
-    public static final int RMI_PORT = 9112;
+    public static final int STOP_PROCESS_EXIT_VAL = 10;
+    public static final int JMX_PORT_RANGE_LOWER = 9100;
+    public static final int JMX_PORT_RANGE_UPPER = 9200;
+    public static final int JMX_PORT = getRandomPortInRange(JMX_PORT_RANGE_LOWER,
+                                                            JMX_PORT_RANGE_UPPER);
+    public static final int JMX_PORT_RANGE_LOWER_SSL = 9201; // 9200 might be RMI Port
+    public static final int JMX_PORT_RANGE_UPPER_SSL = 9300;
+    public static final int JMX_PORT_SSL = getRandomPortInRange(JMX_PORT_RANGE_LOWER_SSL,
+                                                                JMX_PORT_RANGE_UPPER_SSL);
+    public static final int RMI_PORT = JMX_PORT + 1;
+    public static final int RMI_PORT_SSL = JMX_PORT_SSL + 1;
     public static final String READY_MSG = "MainThread: Ready for connections";
     public static final String TEST_CLASS = JMXAgentInterfaceBinding.class.getSimpleName();
     public static final String KEYSTORE_LOC = System.getProperty("test.src", ".") +
@@ -89,8 +89,8 @@
             System.out.println();
             String msg = String.format("DEBUG: Launching java tester for triplet (HOSTNAME,JMX_PORT,RMI_PORT) == (%s,%d,%d)",
                     address,
-                    JMX_PORT,
-                    RMI_PORT);
+                    useSSL ? JMX_PORT_SSL : JMX_PORT,
+                    useSSL ? RMI_PORT_SSL : RMI_PORT);
             System.out.println(msg);
             ProcessThread jvm = runJMXBindingTest(address, useSSL);
             jvms.add(jvm);
@@ -100,9 +100,9 @@
         int failedProcesses = 0;
         for (ProcessThread pt: jvms) {
             try {
-                pt.stopProcess();
+                pt.sendMessage("Exit: " + STOP_PROCESS_EXIT_VAL);
                 pt.join();
-            } catch (InterruptedException e) {
+            } catch (Throwable e) {
                 System.err.println("Failed to stop process: " + pt.getName());
                 throw new RuntimeException("Test failed", e);
             }
@@ -131,10 +131,12 @@
         args.add("-classpath");
         args.add(TEST_CLASSPATH);
         args.add("-Dcom.sun.management.jmxremote.host=" + address);
-        args.add("-Dcom.sun.management.jmxremote.port=" + JMX_PORT);
-        args.add("-Dcom.sun.management.jmxremote.rmi.port=" + RMI_PORT);
+        args.add("-Dcom.sun.management.jmxremote.port=" + (useSSL ? JMX_PORT_SSL : JMX_PORT));
+        args.add("-Dcom.sun.management.jmxremote.rmi.port=" + (useSSL ? RMI_PORT_SSL : RMI_PORT));
         args.add("-Dcom.sun.management.jmxremote.authenticate=false");
         args.add("-Dcom.sun.management.jmxremote.ssl=" + Boolean.toString(useSSL));
+        // This is needed for testing on loopback
+        args.add("-Djava.rmi.server.hostname=" + address);
         if (useSSL) {
             args.add("-Dcom.sun.management.jmxremote.registry.ssl=true");
             args.add("-Djavax.net.ssl.keyStore=" + KEYSTORE_LOC);
@@ -144,8 +146,8 @@
         }
         args.add(TEST_CLASS);
         args.add(address);
-        args.add(Integer.toString(JMX_PORT));
-        args.add(Integer.toString(RMI_PORT));
+        args.add(Integer.toString(useSSL ? JMX_PORT_SSL : JMX_PORT));
+        args.add(Integer.toString(useSSL ? RMI_PORT_SSL : RMI_PORT));
         args.add(Boolean.toString(useSSL));
         try {
             ProcessBuilder builder = ProcessTools.createJavaProcessBuilder(args.toArray(new String[] {}));
@@ -175,35 +177,42 @@
         }
     }
 
+    private static int getRandomPortInRange(int lower, int upper) {
+        if (upper <= lower) {
+            throw new IllegalArgumentException("upper <= lower");
+        }
+        int range = upper - lower;
+        int randPort = lower + (int)(Math.random() * range);
+        return randPort;
+    }
+
     public static void main(String[] args) {
-        List<InetAddress> addrs = getAddressesForLocalHost();
-        if (addrs.size() < 2) {
-            System.out.println("Ignoring manual test since no more than one IPs are configured for 'localhost'");
+        List<InetAddress> addrs = getNonLoopbackAddressesForLocalHost();
+        if (addrs.isEmpty()) {
+            System.out.println("Ignoring test since no non-loopback IPs are available to bind to " +
+                               "in addition to the loopback interface.");
             return;
         }
         JMXInterfaceBindingTest test = new JMXInterfaceBindingTest();
+        // Add loopback interface too as we'd like to verify whether it's
+        // possible to bind to multiple addresses on the same host. This
+        // wasn't possible prior JDK-6425769. It used to bind to *all* local
+        // interfaces. We add loopback here, since that eases test setup.
+        addrs.add(InetAddress.getLoopbackAddress());
         test.run(addrs);
         System.out.println("All tests PASSED.");
     }
 
-    private static List<InetAddress> getAddressesForLocalHost() {
-
+    private static List<InetAddress> getNonLoopbackAddressesForLocalHost() {
+        List<InetAddress> addrs = new ArrayList<>();
         try {
-            return NetworkInterface.networkInterfaces()
-                .flatMap(NetworkInterface::inetAddresses)
-                .filter(JMXInterfaceBindingTest::isNonloopbackLocalhost)
-                .collect(Collectors.toList());
-        } catch (SocketException e) {
+            InetAddress localHost = InetAddress.getLocalHost();
+            if (!localHost.isLoopbackAddress()) {
+                addrs.add(localHost);
+            }
+            return addrs;
+        } catch (UnknownHostException e) {
             throw new RuntimeException("Test failed", e);
         }
     }
-
-    // we need 'real' localhost addresses only (eg. not loopback ones)
-    // so we can bind the remote JMX connector to them
-    private static boolean isNonloopbackLocalhost(InetAddress i) {
-        if (!i.isLoopbackAddress()) {
-            return i.getHostName().toLowerCase().equals("localhost");
-        }
-        return false;
-    }
 }
--- a/test/jdk/sun/net/www/protocol/http/StackTraceTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/net/www/protocol/http/StackTraceTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,22 +21,30 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 4773417 5003746
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * @run main StackTraceTest
  * @summary  HttpURLConnection.getInputStream() produces IOException with
  *           bad stack trace; HttpURLConnection.getInputStream loses
  *           exception message, exception class
  */
 import java.net.*;
 import java.io.IOException;
+import jdk.test.lib.Utils;
 
 public class StackTraceTest {
     public static void main(String[] args) throws Exception {
-        URL url;
-        try (ServerSocket ss = new ServerSocket(0)) {  // refusing socket
-            url = new URL("http://localhost:" + ss.getLocalPort() + "/");
-        }
+        InetSocketAddress refusing = Utils.refusingEndpoint();
+        int port = refusing.getPort();
+        String host = refusing.getAddress().getHostAddress();
+        if (host.contains(":"))
+            host = "[" + host + "]";
+        URL url = URI.create("http://" + host + ":" + port + "/").toURL();
+        System.out.println("URL: " + url);
+
         URLConnection uc = url.openConnection();
 
         // Trigger implicit connection by trying to retrieve bogus
--- a/test/jdk/sun/nio/cs/TestIBMBugs.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/nio/cs/TestIBMBugs.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 6371437 6371422 6371416 6371619 5058184 6371431 6639450 6569191 6577466 8212794
+ * @bug 6371437 6371422 6371416 6371619 5058184 6371431 6639450 6569191 6577466 8212794 8220281
  * @summary Check if the problems reported in above bugs have been fixed
  * @modules jdk.charsets
  */
@@ -31,6 +31,8 @@
 import java.nio.*;
 import java.nio.charset.*;
 import java.util.Arrays;
+import java.util.Locale;
+import java.util.HashSet;
 
 public class TestIBMBugs {
 
@@ -250,6 +252,77 @@
         }
     }
 
+    private static void bug8220281 () throws Exception {
+        if (System.getProperty("os.name").contains("AIX")) {
+            /* Following AIX codesets are used for Java default charset. */
+            /* They should be in sun.nio.cs package on AIX platform.     */
+            String[] codesets = new String[] {
+                "IBM-950", "BIG5-HKSCS", "GB18030", "IBM-1046",
+                "IBM-1124", "IBM-1129", "IBM-1252", "IBM-856",
+                "IBM-858", "IBM-921", "IBM-922", "IBM-932", "IBM-943C",
+                "IBM-eucCN", "IBM-eucJP", "IBM-eucKR", "IBM-eucTW",
+                "ISO8859-1", "ISO8859-15", "ISO8859-2", "ISO8859-4",
+                "ISO8859-5", "ISO8859-6", "ISO8859-7", "ISO8859-8",
+                "ISO8859-9", "TIS-620", "UTF-8", };
+            String[] charsets = new String[] {
+                "x-IBM950", "Big5-HKSCS", "GB18030", "x-IBM1046",
+                "x-IBM1124", "x-IBM1129", "windows-1252", "x-IBM856",
+                "IBM00858", "x-IBM921", "x-IBM922", "x-IBM942C",
+                "x-IBM943C", "x-IBM1383", "x-IBM29626C", "x-IBM970",
+                "x-IBM964", "ISO-8859-1", "ISO-8859-15", "ISO-8859-2",
+                "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7",
+                "ISO-8859-8", "ISO-8859-9", "TIS-620", "UTF-8", };
+            for(int i = 0; i < codesets.length; i++) {
+                Charset cs0 = Charset.forName(codesets[i]);
+                if (!"sun.nio.cs".equals(cs0.getClass().getPackage().getName())) {
+                    throw new Exception(cs0.getClass().getCanonicalName()+" faild");
+                }
+                Charset cs1 = Charset.forName(charsets[i]);
+                if (!cs0.equals(cs1)) {
+                    throw new Exception(codesets[i]+"("+cs0.name()+") failed");
+                }
+            }
+        }
+        for(Charset cs : Charset.availableCharsets().values()) {
+            String csName = cs.name().toLowerCase(Locale.ROOT);
+            String suffix = null;
+            HashSet<String> aliases = new HashSet<String>();
+            for(String s : cs.aliases()) {
+                aliases.add(s.toLowerCase(Locale.ROOT));
+            }
+            aliases.add(csName);
+            if (csName.startsWith("x-ibm-")) {
+                suffix = csName.replaceAll("x-ibm-0*", "");
+            } else if (csName.startsWith("x-ibm")) {
+                suffix = csName.replaceAll("x-ibm0*", "");
+            } else if (csName.startsWith("ibm-")) {
+                suffix = csName.replaceAll("ibm-0*", "");
+            } else if (csName.startsWith("ibm")) {
+                suffix = csName.replaceAll("ibm0*", "");
+            }
+            if ("ibm-thai".equals(csName)) {
+                suffix = "838";
+            }
+            if (null != suffix) {
+                while (suffix.length() < 3) {
+                    suffix = "0"+suffix;
+                }
+                if (!aliases.contains("cp"+suffix)) {
+                    throw new Exception(cs.name()+"\t"+"cp"+suffix);
+                }
+                if (!aliases.contains("ibm"+suffix)) {
+                    throw new Exception(cs.name()+"\t"+"ibm"+suffix);
+                }
+                if (!aliases.contains("ibm-"+suffix)) {
+                    throw new Exception(cs.name()+"\t"+"ibm-"+suffix);
+                }
+                if (!aliases.contains(suffix)) {
+                    throw new Exception(cs.name()+"\t"+suffix);
+                }
+            }
+        }
+    }
+
     public static void main (String[] args) throws Exception {
         bug6577466();
         // need to be tested before any other IBM949C test case
@@ -263,5 +336,6 @@
         bug8202329();
         bug8212794();
         bug8213618();
+        bug8220281();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/ec/SignatureDigestTruncate.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.test.lib.Convert;
+
+import java.security.*;
+import java.security.spec.*;
+import java.math.*;
+import java.util.*;
+
+/*
+ * @test
+ * @bug 8147502
+ * @summary Test that digests are properly truncated before the signature
+ *     is applied. The digest should be truncated to the bit length of the
+ *     group order.
+ * @library /test/lib
+ * @build jdk.test.lib.Convert
+ * @run main SignatureDigestTruncate
+ */
+public class SignatureDigestTruncate {
+
+    /*
+     * A SecureRandom that produces nextBytes in a way that causes the nonce
+     * to be set to the value supplied to the constructor. This class
+     * is specific to the way that the native ECDSA implementation in
+     * SunEC produces nonces from random input. It may not work for all
+     * test cases, and it will need to be updated when the behavior of
+     * SunEC changes.
+     */
+    private static class FixedRandom extends SecureRandom {
+
+        private final byte[] val;
+
+        public FixedRandom(byte[] val) {
+            // SunEC adds one to the value returned, so subtract one here in
+            // order to get back to the correct value.
+            BigInteger biVal = new BigInteger(1, val);
+            biVal = biVal.subtract(BigInteger.ONE);
+            byte[] temp = biVal.toByteArray();
+            this.val = new byte[val.length];
+            int inStartPos = Math.max(0, temp.length - val.length);
+            int outStartPos = Math.max(0, val.length - temp.length);
+            System.arraycopy(temp, inStartPos, this.val, outStartPos,
+                temp.length - inStartPos);
+        }
+
+        @Override
+        public void nextBytes(byte[] bytes) {
+            // SunEC samples (n + 1) * 2 bytes, but only n*2 bytes are used by
+            // the native implementation. So the value must be offset slightly.
+            Arrays.fill(bytes, (byte) 0);
+            int copyLength = Math.min(val.length, bytes.length - 2);
+            System.arraycopy(val, 0, bytes, bytes.length - copyLength - 2,
+                copyLength);
+        }
+    }
+
+    private static void assertEquals(byte[] expected, byte[] actual,
+            String name) {
+        if (!Arrays.equals(actual, expected)) {
+            System.out.println("expect: "
+                    + Convert.byteArrayToHexString(expected));
+            System.out.println("actual: "
+                    + Convert.byteArrayToHexString(actual));
+            throw new RuntimeException("Incorrect " + name + " value");
+        }
+    }
+
+    private static void runTest(String alg, String curveName,
+        String privateKeyStr, String msgStr, String kStr, String sigStr)
+        throws Exception {
+
+        System.out.println("Testing " + alg + " with " + curveName);
+
+        byte[] privateKey = Convert.hexStringToByteArray(privateKeyStr);
+        byte[] msg = Convert.hexStringToByteArray(msgStr);
+        byte[] k = Convert.hexStringToByteArray(kStr);
+        byte[] expectedSig = Convert.hexStringToByteArray(sigStr);
+
+        AlgorithmParameters params =
+            AlgorithmParameters.getInstance("EC", "SunEC");
+        params.init(new ECGenParameterSpec(curveName));
+        ECParameterSpec ecParams =
+            params.getParameterSpec(ECParameterSpec.class);
+
+        KeyFactory kf = KeyFactory.getInstance("EC", "SunEC");
+        BigInteger s = new BigInteger(1, privateKey);
+        ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(s, ecParams);
+        PrivateKey privKey = kf.generatePrivate(privKeySpec);
+
+        Signature sig = Signature.getInstance(alg, "SunEC");
+        sig.initSign(privKey, new FixedRandom(k));
+        sig.update(msg);
+        byte[] computedSig = sig.sign();
+        assertEquals(expectedSig, computedSig, "signature");
+    }
+
+    public static void main(String[] args) throws Exception {
+        runTest("SHA384withECDSAinP1363Format", "sect283r1",
+            "abcdef10234567", "010203040506070809",
+            "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d" +
+            "1e1f20212223",
+            "01d7544b5d3935216bd45e2f8042537e1e0296a11e0eb96666199281b409" +
+            "42abccd5358a035de8a314d3e6c2a97614daebf5fb1313540eec3f9a3272" +
+            "068aa10922ccae87d255c84c");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/pkcs11/tls/tls12/TestTLS12.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc.
+ * 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 8029661
+ * @summary Test TLS 1.2
+ * @modules java.base/sun.security.internal.spec
+ *          java.base/sun.security.util
+ *          java.base/com.sun.crypto.provider
+ * @library /test/lib ../..
+ * @run main/othervm/timeout=120 TestTLS12
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.SecureRandom;
+import java.security.Security;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManagerFactory;
+
+import sun.security.internal.spec.TlsMasterSecretParameterSpec;
+import sun.security.internal.spec.TlsPrfParameterSpec;
+import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
+
+public final class TestTLS12 extends SecmodTest {
+
+    private static final boolean enableDebug = true;
+
+    private static Provider sunPKCS11NSSProvider;
+    private static Provider sunJCEProvider;
+    private static KeyStore ks;
+    private static KeyStore ts;
+    private static char[] passphrase = "JAHshj131@@".toCharArray();
+    private static RSAPrivateKey privateKey;
+    private static RSAPublicKey publicKey;
+
+    public static void main(String[] args) throws Exception {
+        try {
+            initialize();
+        } catch (Exception e) {
+            System.out.println("Test skipped: failure during" +
+                    " initialization");
+            if (enableDebug) {
+                System.out.println(e);
+            }
+            return;
+        }
+
+        if (shouldRun()) {
+            // Test against JCE
+            testTlsAuthenticationCodeGeneration();
+
+            // Self-integrity test (complete TLS 1.2 communication)
+            new testTLS12SunPKCS11Communication().run();
+
+            System.out.println("Test PASS - OK");
+        } else {
+            System.out.println("Test skipped: TLS 1.2 mechanisms" +
+                    " not supported by current SunPKCS11 back-end");
+        }
+    }
+
+    private static boolean shouldRun() {
+        if (sunPKCS11NSSProvider == null) {
+            return false;
+        }
+        try {
+            KeyGenerator.getInstance("SunTls12MasterSecret",
+                    sunPKCS11NSSProvider);
+            KeyGenerator.getInstance(
+                    "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);
+            KeyGenerator.getInstance("SunTls12Prf", sunPKCS11NSSProvider);
+        } catch (NoSuchAlgorithmException e) {
+            return false;
+        }
+        return true;
+    }
+
+    private static void testTlsAuthenticationCodeGeneration()
+            throws Exception {
+        // Generate RSA Pre-Master Secret in SunPKCS11 provider
+        SecretKey rsaPreMasterSecret = null;
+        @SuppressWarnings("deprecation")
+        TlsRsaPremasterSecretParameterSpec rsaPreMasterSecretSpec =
+                new TlsRsaPremasterSecretParameterSpec(0x0303, 0x0303);
+        {
+            KeyGenerator rsaPreMasterSecretKG = KeyGenerator.getInstance(
+                    "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);
+            rsaPreMasterSecretKG.init(rsaPreMasterSecretSpec, null);
+            rsaPreMasterSecret = rsaPreMasterSecretKG.generateKey();
+        }
+
+        // Get RSA Pre-Master Secret in plain (from SunPKCS11 provider)
+        byte[] rsaPlainPreMasterSecret = null;
+        {
+            Cipher rsaPreMasterSecretWrapperCipher =
+                    Cipher.getInstance("RSA/ECB/PKCS1Padding",
+                            sunPKCS11NSSProvider);
+            rsaPreMasterSecretWrapperCipher.init(Cipher.WRAP_MODE, publicKey,
+                    new SecureRandom());
+            byte[] rsaEncryptedPreMasterSecret =
+                    rsaPreMasterSecretWrapperCipher.wrap(rsaPreMasterSecret);
+            Cipher rsaPreMasterSecretUnwrapperCipher =
+                    Cipher.getInstance("RSA/ECB/PKCS1Padding", sunJCEProvider);
+            rsaPreMasterSecretUnwrapperCipher.init(Cipher.UNWRAP_MODE,
+                    privateKey, rsaPreMasterSecretSpec);
+            rsaPlainPreMasterSecret = rsaPreMasterSecretUnwrapperCipher.unwrap(
+                    rsaEncryptedPreMasterSecret, "TlsRsaPremasterSecret",
+                    Cipher.SECRET_KEY).getEncoded();
+
+            if (enableDebug) {
+                System.out.println("rsaPlainPreMasterSecret:");
+                for (byte b : rsaPlainPreMasterSecret) {
+                    System.out.printf("%02X, ", b);
+                }
+                System.out.println("");
+            }
+        }
+
+        // Generate Master Secret
+        SecretKey sunPKCS11MasterSecret = null;
+        SecretKey jceMasterSecret = null;
+        {
+            KeyGenerator sunPKCS11MasterSecretGenerator =
+                    KeyGenerator.getInstance("SunTls12MasterSecret",
+                            sunPKCS11NSSProvider);
+            KeyGenerator jceMasterSecretGenerator = KeyGenerator.getInstance(
+                    "SunTls12MasterSecret", sunJCEProvider);
+            @SuppressWarnings("deprecation")
+            TlsMasterSecretParameterSpec sunPKCS11MasterSecretSpec =
+                    new TlsMasterSecretParameterSpec(rsaPreMasterSecret, 3, 3,
+                            new byte[32], new byte[32], "SHA-256", 32, 64);
+            @SuppressWarnings("deprecation")
+            TlsMasterSecretParameterSpec jceMasterSecretSpec =
+                    new TlsMasterSecretParameterSpec(
+                            new SecretKeySpec(rsaPlainPreMasterSecret,
+                                    "Generic"), 3, 3, new byte[32],
+                            new byte[32], "SHA-256", 32, 64);
+            sunPKCS11MasterSecretGenerator.init(sunPKCS11MasterSecretSpec,
+                    null);
+            jceMasterSecretGenerator.init(jceMasterSecretSpec, null);
+            sunPKCS11MasterSecret =
+                    sunPKCS11MasterSecretGenerator.generateKey();
+            jceMasterSecret = jceMasterSecretGenerator.generateKey();
+            if (enableDebug) {
+                System.out.println("Master Secret (SunJCE):");
+                if (jceMasterSecret != null) {
+                    for (byte b : jceMasterSecret.getEncoded()) {
+                        System.out.printf("%02X, ", b);
+                    }
+                    System.out.println("");
+                }
+            }
+        }
+
+        // Generate authentication codes
+        byte[] sunPKCS11AuthenticationCode = null;
+        byte[] jceAuthenticationCode = null;
+        {
+            // Generate SunPKCS11 authentication code
+            {
+                @SuppressWarnings("deprecation")
+                TlsPrfParameterSpec sunPKCS11AuthenticationCodeSpec =
+                        new TlsPrfParameterSpec(sunPKCS11MasterSecret,
+                                "client finished", "a".getBytes(), 12,
+                                "SHA-256", 32, 64);
+                KeyGenerator sunPKCS11AuthCodeGenerator =
+                        KeyGenerator.getInstance("SunTls12Prf",
+                                sunPKCS11NSSProvider);
+                sunPKCS11AuthCodeGenerator.init(
+                        sunPKCS11AuthenticationCodeSpec);
+                sunPKCS11AuthenticationCode =
+                        sunPKCS11AuthCodeGenerator.generateKey().getEncoded();
+            }
+
+            // Generate SunJCE authentication code
+            {
+                @SuppressWarnings("deprecation")
+                TlsPrfParameterSpec jceAuthenticationCodeSpec =
+                        new TlsPrfParameterSpec(jceMasterSecret,
+                                "client finished", "a".getBytes(), 12,
+                                "SHA-256", 32, 64);
+                KeyGenerator jceAuthCodeGenerator =
+                        KeyGenerator.getInstance("SunTls12Prf",
+                                sunJCEProvider);
+                jceAuthCodeGenerator.init(jceAuthenticationCodeSpec);
+                jceAuthenticationCode =
+                        jceAuthCodeGenerator.generateKey().getEncoded();
+            }
+
+            if (enableDebug) {
+                System.out.println("SunPKCS11 Authentication Code: ");
+                for (byte b : sunPKCS11AuthenticationCode) {
+                    System.out.printf("%02X, ", b);
+                }
+                System.out.println("");
+                System.out.println("SunJCE Authentication Code: ");
+                for (byte b : jceAuthenticationCode) {
+                    System.out.printf("%02X, ", b);
+                }
+                System.out.println("");
+            }
+        }
+
+        if (sunPKCS11AuthenticationCode == null ||
+                jceAuthenticationCode == null ||
+                sunPKCS11AuthenticationCode.length == 0 ||
+                jceAuthenticationCode.length == 0 ||
+                !Arrays.equals(sunPKCS11AuthenticationCode,
+                        jceAuthenticationCode)) {
+            throw new Exception("Authentication codes from JCE" +
+                        " and SunPKCS11 differ.");
+        }
+    }
+
+    private static class testTLS12SunPKCS11Communication {
+        public static void run() throws Exception {
+            SSLEngine[][] enginesToTest = getSSLEnginesToTest();
+
+            for (SSLEngine[] engineToTest : enginesToTest) {
+
+                SSLEngine clientSSLEngine = engineToTest[0];
+                SSLEngine serverSSLEngine = engineToTest[1];
+
+                // SSLEngine code based on RedhandshakeFinished.java
+
+                boolean dataDone = false;
+
+                ByteBuffer clientOut = null;
+                ByteBuffer clientIn = null;
+                ByteBuffer serverOut = null;
+                ByteBuffer serverIn = null;
+                ByteBuffer cTOs;
+                ByteBuffer sTOc;
+
+                SSLSession session = clientSSLEngine.getSession();
+                int appBufferMax = session.getApplicationBufferSize();
+                int netBufferMax = session.getPacketBufferSize();
+
+                clientIn = ByteBuffer.allocate(appBufferMax + 50);
+                serverIn = ByteBuffer.allocate(appBufferMax + 50);
+
+                cTOs = ByteBuffer.allocateDirect(netBufferMax);
+                sTOc = ByteBuffer.allocateDirect(netBufferMax);
+
+                clientOut = ByteBuffer.wrap(
+                        "Hi Server, I'm Client".getBytes());
+                serverOut = ByteBuffer.wrap(
+                        "Hello Client, I'm Server".getBytes());
+
+                SSLEngineResult clientResult;
+                SSLEngineResult serverResult;
+
+                while (!dataDone) {
+                    clientResult = clientSSLEngine.wrap(clientOut, cTOs);
+                    runDelegatedTasks(clientResult, clientSSLEngine);
+                    serverResult = serverSSLEngine.wrap(serverOut, sTOc);
+                    runDelegatedTasks(serverResult, serverSSLEngine);
+                    cTOs.flip();
+                    sTOc.flip();
+
+                    if (enableDebug) {
+                        System.out.println("Client -> Network");
+                        printTlsNetworkPacket("", cTOs);
+                        System.out.println("");
+                        System.out.println("Server -> Network");
+                        printTlsNetworkPacket("", sTOc);
+                        System.out.println("");
+                    }
+
+                    clientResult = clientSSLEngine.unwrap(sTOc, clientIn);
+                    runDelegatedTasks(clientResult, clientSSLEngine);
+                    serverResult = serverSSLEngine.unwrap(cTOs, serverIn);
+                    runDelegatedTasks(serverResult, serverSSLEngine);
+
+                    cTOs.compact();
+                    sTOc.compact();
+
+                    if (!dataDone &&
+                            (clientOut.limit() == serverIn.position()) &&
+                            (serverOut.limit() == clientIn.position())) {
+                        checkTransfer(serverOut, clientIn);
+                        checkTransfer(clientOut, serverIn);
+                        dataDone = true;
+                    }
+                }
+            }
+        }
+
+        static void printTlsNetworkPacket(String prefix, ByteBuffer bb) {
+            ByteBuffer slice = bb.slice();
+            byte[] buffer = new byte[slice.remaining()];
+            slice.get(buffer);
+            for (int i = 0; i < buffer.length; i++) {
+                System.out.printf("%02X, ", (byte)(buffer[i] & (byte)0xFF));
+                if (i % 8 == 0 && i % 16 != 0) {
+                    System.out.print(" ");
+                }
+                if (i % 16 == 0) {
+                    System.out.println("");
+                }
+            }
+            System.out.flush();
+        }
+
+        private static void checkTransfer(ByteBuffer a, ByteBuffer b)
+                throws Exception {
+            a.flip();
+            b.flip();
+            if (!a.equals(b)) {
+                throw new Exception("Data didn't transfer cleanly");
+            }
+            a.position(a.limit());
+            b.position(b.limit());
+            a.limit(a.capacity());
+            b.limit(b.capacity());
+        }
+
+        private static void runDelegatedTasks(SSLEngineResult result,
+                SSLEngine engine) throws Exception {
+
+            if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+                Runnable runnable;
+                while ((runnable = engine.getDelegatedTask()) != null) {
+                    runnable.run();
+                }
+                HandshakeStatus hsStatus = engine.getHandshakeStatus();
+                if (hsStatus == HandshakeStatus.NEED_TASK) {
+                    throw new Exception(
+                        "handshake shouldn't need additional tasks");
+                }
+            }
+        }
+
+        private static SSLEngine[][] getSSLEnginesToTest() throws Exception {
+            SSLEngine[][] enginesToTest = new SSLEngine[2][2];
+            String[][] preferredSuites = new String[][]{ new String[] {
+                    "TLS_RSA_WITH_AES_128_CBC_SHA256"
+            },  new String[] {
+                    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"
+            }};
+            for (int i = 0; i < enginesToTest.length; i++) {
+                enginesToTest[i][0] = createSSLEngine(true);
+                enginesToTest[i][1] = createSSLEngine(false);
+                enginesToTest[i][0].setEnabledCipherSuites(preferredSuites[i]);
+                enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]);
+            }
+            return enginesToTest;
+        }
+
+        static private SSLEngine createSSLEngine(boolean client)
+                throws Exception {
+            SSLEngine ssle;
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX", "SunJSSE");
+            kmf.init(ks, passphrase);
+
+            TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
+            tmf.init(ts);
+
+            SSLContext sslCtx = SSLContext.getInstance("TLSv1.2", "SunJSSE");
+            sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+            ssle = sslCtx.createSSLEngine("localhost", 443);
+            ssle.setUseClientMode(client);
+            SSLParameters sslParameters = ssle.getSSLParameters();
+            ssle.setSSLParameters(sslParameters);
+
+            return ssle;
+        }
+    }
+
+    private static void initialize() throws Exception {
+        if (initSecmod() == false) {
+            return;
+        }
+        String configName = BASE + SEP + "nss.cfg";
+        sunPKCS11NSSProvider = getSunPKCS11(configName);
+        System.out.println("SunPKCS11 provider: " + sunPKCS11NSSProvider);
+
+        List<Provider> installedProviders = new LinkedList<>();
+        for (Provider p : Security.getProviders()){
+            installedProviders.add(p);
+            Security.removeProvider(p.getName());
+        }
+        Security.addProvider(sunPKCS11NSSProvider);
+        for (Provider p : installedProviders){
+            String providerName = p.getName();
+            if (providerName.equals("SunJSSE") ||
+                    providerName.equals("SUN") ||
+                    providerName.equals("SunJCE")) {
+                Security.addProvider(p);
+                if (providerName.equals("SunJCE")) {
+                    sunJCEProvider = p;
+                }
+            }
+        }
+
+        ks = KeyStore.getInstance("PKCS11", sunPKCS11NSSProvider);
+        ks.load(null, "test12".toCharArray());
+        ts = ks;
+
+        KeyStore ksPlain = readTestKeyStore();
+        privateKey = (RSAPrivateKey)ksPlain.getKey("rh_rsa_sha256",
+                passphrase);
+        publicKey = (RSAPublicKey)ksPlain.getCertificate(
+                "rh_rsa_sha256").getPublicKey();
+
+        // Extended Master Secret is not currently supported in SunPKCS11
+        // cryptographic provider
+        System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
+        String disabledAlgorithms =
+                Security.getProperty("jdk.tls.disabledAlgorithms");
+        if (disabledAlgorithms.length() > 0) {
+            disabledAlgorithms += ", ";
+        }
+        // RSASSA-PSS is not currently supported in SunPKCS11
+        // cryptographic provider
+        disabledAlgorithms += "RSASSA-PSS";
+        Security.setProperty("jdk.tls.disabledAlgorithms", disabledAlgorithms);
+    }
+
+    private static KeyStore readTestKeyStore() throws Exception {
+        File file = new File(System.getProperty("test.src", "."), "keystore");
+        InputStream in = new FileInputStream(file);
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(in, "passphrase".toCharArray());
+        in.close();
+        return ks;
+    }
+}
Binary file test/jdk/sun/security/pkcs11/tls/tls12/cert8.db has changed
Binary file test/jdk/sun/security/pkcs11/tls/tls12/key3.db has changed
Binary file test/jdk/sun/security/pkcs11/tls/tls12/keystore has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/sun/security/pkcs11/tls/tls12/nss.cfg	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,19 @@
+
+name = NSSKeyStore
+
+nssSecmodDirectory = ${pkcs11test.nss.db}
+
+nssLibraryDirectory = ${pkcs11test.nss.libdir}
+
+nssModule = fips
+
+# NSS needs CKA_NETSCAPE_DB for DSA and DH private keys
+# just put an arbitrary value in there to make it happy
+
+attributes(*,CKO_PRIVATE_KEY,CKK_DSA) = {
+  CKA_NETSCAPE_DB = 0h00
+}
+
+attributes(*,CKO_PRIVATE_KEY,CKK_DH) = {
+  CKA_NETSCAPE_DB = 0h00
+}
Binary file test/jdk/sun/security/pkcs11/tls/tls12/secmod.db has changed
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 import java.security.cert.X509Certificate;
 import java.util.Date;
 import java.util.Locale;
+import java.util.TimeZone;
 
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.util.JarUtils;
@@ -46,6 +47,7 @@
      * and checks that proper warnings are shown.
      */
     public static void main(String[] args) throws Throwable {
+
         Locale reservedLocale = Locale.getDefault();
         Locale.setDefault(Locale.US);
 
@@ -61,6 +63,9 @@
     private void start() throws Throwable {
         String timezone = System.getProperty("user.timezone");
         System.out.println(String.format("Timezone = %s", timezone));
+        if (timezone != null) {
+            TimeZone.setDefault(TimeZone.getTimeZone(timezone));
+        }
 
         // create a jar file that contains one class file
         Utils.createFiles(FIRST_FILE);
@@ -73,10 +78,11 @@
                 "-validity", Integer.toString(VALIDITY));
 
         Date expirationDate = getCertExpirationDate();
+        System.out.println("Cert expiration: " + expirationDate);
 
         // sign jar file
         OutputAnalyzer analyzer = jarsigner(
-                "-J-Duser.timezone=" + timezone,
+                userTimezoneOpt(timezone),
                 "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
@@ -90,7 +96,7 @@
 
         // verify signed jar
         analyzer = jarsigner(
-                "-J-Duser.timezone=" + timezone,
+                userTimezoneOpt(timezone),
                 "-verify",
                 "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
@@ -103,7 +109,7 @@
 
         // verify signed jar in strict mode
         analyzer = jarsigner(
-                "-J-Duser.timezone=" + timezone,
+                userTimezoneOpt(timezone),
                 "-verify",
                 "-strict",
                 "-keystore", KEYSTORE,
@@ -117,6 +123,10 @@
         System.out.println("Test passed");
     }
 
+    private static String userTimezoneOpt(String timezone) {
+        return timezone == null ? null : "-J-Duser.timezone=" + timezone;
+    }
+
     private static Date getCertExpirationDate() throws Exception {
         KeyStore ks = KeyStore.getInstance("JKS");
         try (InputStream in = new FileInputStream(KEYSTORE)) {
--- a/test/jdk/sun/security/tools/jarsigner/warnings/Test.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/Test.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,12 +21,13 @@
  * questions.
  */
 
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.stream.Collectors;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
 
 /**
  * Base class.
@@ -259,7 +260,9 @@
         cmd.add(tool);
         cmd.add("-J-Duser.language=en");
         cmd.add("-J-Duser.country=US");
-        cmd.addAll(Arrays.asList(args));
+        cmd.addAll(Arrays.asList(args).stream().filter(arg -> {
+            return arg != null && !arg.isEmpty();
+        }).collect(Collectors.toList()));
         return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()]));
     }
 }
--- a/test/jdk/sun/tools/jstat/lineCounts3.awk	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/tools/jstat/lineCounts3.awk	Tue Mar 26 09:05:10 2019 -0400
@@ -23,7 +23,7 @@
 	    headerlines++;
 	}
 
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+)|-[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/	{
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/	{
 	    datalines++;
 	}
 
--- a/test/jdk/sun/tools/jstat/lineCounts4.awk	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/jdk/sun/tools/jstat/lineCounts4.awk	Tue Mar 26 09:05:10 2019 -0400
@@ -26,7 +26,7 @@
 	    headerlines++;
 	}
 
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+)|-[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/	{
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/	{
 	    if (headerlines == 2) {
 	        datalines2++;
 	    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/launcher/JniInvocationTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8213362
+ * @comment Test uses custom launcher that starts VM using JNI via libjli, only for MacOS
+ * @requires os.family == "mac"
+ * @library /test/lib
+ * @run main/native JniInvocationTest
+ */
+
+import java.util.Map;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class JniInvocationTest {
+    public static void main(String[] args) throws IOException {
+        Path launcher = Paths.get(System.getProperty("test.nativepath"), "JniInvocationTest");
+        System.out.println("Launcher = " + launcher + (Files.exists(launcher) ? " (exists)" : " (not exists)"));
+        ProcessBuilder pb = new ProcessBuilder(launcher.toString());
+        Map<String, String> env = pb.environment();
+        String libdir = Paths.get(Utils.TEST_JDK).resolve("lib").toAbsolutePath().toString();
+        env.compute(Platform.sharedLibraryPathVariableName(), (k, v) -> (k == null) ? libdir : v + ":" + libdir);
+        OutputAnalyzer outputf = new OutputAnalyzer(pb.start());
+        outputf.shouldHaveExitValue(0);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/tools/launcher/exeJniInvocationTest.c	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "jni.h"
+#include "stdio.h"
+#include "stdlib.h"
+
+int main(int argc, char** args) {
+    JavaVMInitArgs vm_args;
+    JNIEnv *env;
+    JavaVM *vm;
+    int i =0;
+    jint result;
+
+    vm_args.version = JNI_VERSION_1_2;
+    vm_args.ignoreUnrecognized = JNI_FALSE;
+
+    JavaVMOption option1[2];
+    option1[0].optionString="-XX:+PrintCommandLineFlags";
+    option1[1].optionString="-Xrs";
+
+    vm_args.options=option1;
+    vm_args.nOptions=2;
+
+    // Print the VM options in use
+    printf("initVM: numOptions = %d\n", vm_args.nOptions);
+    for (i = 0; i < vm_args.nOptions; i++)
+    {
+        printf("\tvm_args.options[%d].optionString = %s\n", i, vm_args.options[i].optionString);
+    }
+
+    // Initialize VM with given options
+    result = JNI_CreateJavaVM( &vm, (void **) &env, &vm_args );
+    if (result != 0) {
+        printf("ERROR: cannot create JAVA VM.\n");
+        exit(-1);
+    }
+
+    (*vm)->DestroyJavaVM(vm);
+}
+
--- a/test/jdk/vm/JniInvocationTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 8213362
- * @comment Test uses custom launcher that starts VM using JNI via libjli, only for MacOS
- * @requires os.family == "mac"
- * @library /test/lib
- * @run main/native JniInvocationTest
- */
-
-import java.util.Map;
-import jdk.test.lib.Platform;
-import jdk.test.lib.Utils;
-import jdk.test.lib.process.OutputAnalyzer;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-public class JniInvocationTest {
-    public static void main(String[] args) throws IOException {
-        Path launcher = Paths.get(System.getProperty("test.nativepath"), "JniInvocationTest");
-        System.out.println("Launcher = " + launcher + (Files.exists(launcher) ? " (exists)" : " (not exists)"));
-        ProcessBuilder pb = new ProcessBuilder(launcher.toString());
-        Map<String, String> env = pb.environment();
-        String libdir = Paths.get(Utils.TEST_JDK).resolve("lib").toAbsolutePath().toString();
-        env.compute(Platform.sharedLibraryPathVariableName(), (k, v) -> (k == null) ? libdir : v + ":" + libdir);
-        OutputAnalyzer outputf = new OutputAnalyzer(pb.start());
-        outputf.shouldHaveExitValue(0);
-    }
-}
-
--- a/test/jdk/vm/exeJniInvocationTest.c	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "jni.h"
-#include "stdio.h"
-#include "stdlib.h"
-
-int main(int argc, char** args) {
-    JavaVMInitArgs vm_args;
-    JNIEnv *env;
-    JavaVM *vm;
-    int i =0;
-    jint result;
-
-    vm_args.version = JNI_VERSION_1_2;
-    vm_args.ignoreUnrecognized = JNI_FALSE;
-
-    JavaVMOption option1[2];
-    option1[0].optionString="-XX:+PrintCommandLineFlags";
-    option1[1].optionString="-Xrs";
-
-    vm_args.options=option1;
-    vm_args.nOptions=2;
-
-    // Print the VM options in use
-    printf("initVM: numOptions = %d\n", vm_args.nOptions);
-    for (i = 0; i < vm_args.nOptions; i++)
-    {
-        printf("\tvm_args.options[%d].optionString = %s\n", i, vm_args.options[i].optionString);
-    }
-
-    // Initialize VM with given options
-    result = JNI_CreateJavaVM( &vm, (void **) &env, &vm_args );
-    if (result != 0) {
-        printf("ERROR: cannot create JAVA VM.\n");
-        exit(-1);
-    }
-
-    (*vm)->DestroyJavaVM(vm);
-}
-
--- a/test/jdk/vm/gc/ArraySize.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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 4063078
- * @summary Allocating a ridiculously large array should not crash the VM
- * @run main/othervm -Xmx32m -Xms32m ArraySize
- */
-
-public class ArraySize {
-
-    public static void main(String[] args) throws Exception {
-        boolean thrown = false;
-        try {
-            byte[] buf = new byte[Integer.MAX_VALUE - 1];
-            System.out.print(buf[0]);
-        } catch (OutOfMemoryError x) {
-            thrown = true;
-        }
-        if (! thrown) {
-            throw new Exception("Didn't throw expected OutOfMemoryError");
-        }
-    }
-
-}
--- a/test/jdk/vm/gc/InfiniteList.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +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 4098578
- * @summary Check if the VM properly throws OutOfMemoryError
- * @author Sheng Liang
- * @run main/othervm -Xmx25M InfiniteList
- */
-public class InfiniteList {
-    InfiniteList next;
-    long data[] = new long[50000];
-    public static void main(String[] args) throws Exception {
-        InfiniteList p, q;
-        p = new InfiniteList ();
-        p.data[p.data.length -1 ] = 999;
-        try {
-            while (p != null) {
-                q = new InfiniteList ();
-                q.next = p;
-                p = q;
-            }
-            throw new Exception ("OutOfMemoryError not thrown as expected.");
-        } catch (OutOfMemoryError e) {
-            return;
-        }
-    }
-}
--- a/test/jdk/vm/jit/BadLogicCode.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +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 4157675
- * @summary Solaris JIT generates bad code for logic expression
- * @author Tom Rodriguez
- */
-
-public class BadLogicCode {
-    static int values[] = {Integer.MIN_VALUE, -1, 0, 1, 4, 16, 31,
-                           32, 33, Integer.MAX_VALUE};
-    static char b[][] = {null, new char[32]};
-    static boolean nullPtr = false, indexOutBnd = false;
-    static boolean indexOutBnd2 = false;
-
-    public static void main(String args[]) throws Exception{
-        int i = 1, j = 4, k = 9;
-
-        nullPtr = (b[i] == null);
-
-        int bufLen = nullPtr ? 0 : b[i].length;
-        indexOutBnd = (values[j] < 0)
-            || (values[j] > bufLen)
-            || (values[k] < 0)
-            || ((values[j] + values[k]) > bufLen)
-            ||((values[j] + values[k]) < 0);
-
-        indexOutBnd2 = (values[j] < 0);
-        indexOutBnd2 = indexOutBnd2 || (values[j] > bufLen);
-        indexOutBnd2 = indexOutBnd2 || (values[k] < 0);
-        indexOutBnd2 = indexOutBnd2 || ((values[j] + values[k]) > bufLen);
-        indexOutBnd2 = indexOutBnd2 ||((values[j] + values[k]) < 0);
-        if (indexOutBnd != indexOutBnd2)
-            throw new Error("logic expression generate different results");
-    }
-}
--- a/test/jdk/vm/jit/ExceptionInInit.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +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 4165973
- * @summary Attempt to read inaccessible property can produce
- *          exception of the wrong type.
- * @author Tom Rodriguez
- *
- * @modules java.rmi
- */
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-public class ExceptionInInit {
-
-    public static void main(String[] args) {
-
-        Test test = null;
-
-        try {
-            System.setSecurityManager(new java.rmi.RMISecurityManager());
-            Test.showTest();
-        } catch (ExceptionInInitializerError e) {
-        }
-    }
-
-    public static class FooBar {
-        static String test = "test";
-        FooBar(String test) {
-            this.test = test;
-        }
-    }
-
-    public static class Test extends FooBar {
-
-        /*
-         * An AccessControlException is thrown in the static initializer of the
-         * class FooBar. This exception should produce an ExceptionInInitializer
-         * error. Instead it causes a more cryptic ClassNotFound error.
-         *
-         * The following is an excerpt from the output from java.security.debug=all
-         *
-         * access: access denied (java.util.PropertyPermission test.src read)
-         * java.lang.Exception: Stack trace
-         *         at java.lang.Thread.dumpStack(Thread.java:938)
-         *         at java.security.AccessControlContext.checkPermission(AccessControlContext.java:184)
-         *         at java.security.AccessController.checkPermission(AccessController.java:402)
-         *         at java.lang.SecurityManager.checkPermission(SecurityManager.java:516)
-         *         at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1035)
-         *         at java.lang.System.getProperty(System.java:441)
-         *         at sun.security.action.GetPropertyAction.run(GetPropertyAction.java:73)
-         *         at java.security.AccessController.doPrivileged(Native Method)
-         *         at ExceptionInInit$Test.&#60clinit>(ExceptionInInit.java:33)
-         *         at ExceptionInInit.main(ExceptionInInit.java:18)
-         * access: domain that failed ProtectionDomain (file:/tmp/exceptionInInit/<no certificates>)
-         *
-         * The following exception is occurring when this test program tries
-         * to access the test.src property.
-         */
-        private static String test =
-            AccessController.doPrivileged((PrivilegedAction<String>)() -> System.getProperty("test.src", "."));
-
-        Test(String test) {
-            super(test);
-        }
-        public static void showTest() {
-            System.err.println(test);
-        }
-    }
-}
--- a/test/jdk/vm/jit/JITClassInit.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +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 4154887
- * @summary self-parser test causes JDK 1.2 Beta4K segmentation fault
- * @run main/othervm JITClassInit
- * @author Tom Rodriguez
- */
-
-public class JITClassInit {
-    public static void main(String[] args) {
-        Token t = new Token();
-        new TokenTable();
-    }
-
-}
-
-class TokenTable {
-    public TokenTable() {
-        new TokenTypeIterator(this);
-    }
-
-    public void for_token_type(Token t) {
-        t.keyword_character_class();
-    }
-}
-
-class Token {
-    public Object keyword_character_class() {
-        return new Object();
-    }
-}
-
-class NameOrKeywordToken extends Token {
-    static TokenTable kt = new TokenTable();
-    public Object keyword_character_class() {
-        return new Object();
-    }
-}
-
-class CapKeywordToken extends NameOrKeywordToken {
-    public Object keyword_character_class() {
-        return new Object();
-    }
-};
-
-
-class TokenTypeIterator {
-    public TokenTypeIterator(TokenTable c) {
-        c.for_token_type(new CapKeywordToken());
-        c.for_token_type(new NameOrKeywordToken());
-    }
-}
--- a/test/jdk/vm/runtime/ExplicitArithmeticCheck.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +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 4221448
- * @summary Use explicit check for integer arithmetic exception on win32.
- */
-
-public class ExplicitArithmeticCheck {
-    public static void main(String argv[]) throws Exception {
-        for (int i = 0; i < 64; i++) {
-          boolean result = false;
-          int n;
-          try {
-              n = 0 / 0;
-          } catch (ArithmeticException e) {
-              result = true;
-          }
-          if (result == false) {
-            throw new Error("Failed to throw correct exception!");
-          }
-          result = false;
-          try {
-              n = 0 % 0;
-          } catch (ArithmeticException e) {
-              result = true;
-          }
-          if (result == false) {
-            throw new Error("Failed to throw correct exception!");
-          }
-          try {
-              n = 0x80000000 / -1;
-          } catch (Throwable t) {
-            throw new Error("Failed to throw correct exception!");
-          }
-          if (n != 0x80000000) {
-            throw new Error("Incorrect integer arithmetic ! ");
-          }
-          try {
-              n = 0x80000000 % -1;
-          } catch (Throwable t) {
-            throw new Error("Failed to throw correct exception!");
-          }
-          if (n != 0) {
-            throw new Error("Incorrect integer arithmetic!");
-          }
-        }
-    }
-}
--- a/test/jdk/vm/runtime/MonitorCacheMaybeExpand_DeadLock.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +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 4087516
- * @summary Incorrect locking leads to deadlock in monitorCacheMaybeExpand.
- * @author Anand Palaniswamy
- * @build MonitorCacheMaybeExpand_DeadLock
- * @run main/othervm MonitorCacheMaybeExpand_DeadLock
- */
-
-/**
- * Background on the bug:
- *
- *     The thread local monitor cache had a locking bug (till
- *     1.2beta1) where two threads trying to expand the monitor cache
- *     at the same time would cause deadlock. The code paths that the
- *     two threads must be executing for this to happen is described
- *     in the bug report.
- *
- * Caveat and red-flag:
- *
- *     Since deadlocks are very timing dependent, there is a good
- *     chance this test case will not catch the bug most of the time
- *     -- on your machine and setting, it is _possible_ that the two
- *     threads might not try a monitorCacheExpand at the same
- *     time. But in practice, on Solaris native threads, this program
- *     deadlocks the VM in about 2 seconds pretty consistently,
- *     whether MP or not.
- *
- *     The rationale for running this test despite this rather large
- *     caveat is that at worst, it can do no harm.
- *
- * The idea:
- *
- *     Is to create two monitor hungry threads.
- *
- *     Originally Tom Rodriguez and I suspected that this weird state
- *     of two threads trying to expand monitor cache can happen only
- *     if:
- *
- *         Thread 1: Is in the middle of a monitorCacheMaybeExpand.
- *         Thread 2: Runs GC and tries to freeClasses(). This causes
- *                   sysFree() to be invoked, which in turn needs a
- *                   mutex_lock -- and oops, we end up deadlocking
- *                   with 1 on green_threads.
- *
- *     Which is why this test tries to cause class GC at regular
- *     intervals.
- *
- *     Turns out that the GC is not required. Two instances of the
- *     monitor hungry threads deadlock the VM pretty quick. :-) Infact
- *     the static initializer in the forName'd classes running
- *     alongside one of the hungry threads is sufficient to
- *     deadlock. Still keep the GC stuff just-in-case (and also
- *     because I wrote it :-).
- *
- */
-public class MonitorCacheMaybeExpand_DeadLock {
-
-    /**
-     * A monitor-hungry thread.
-     */
-    static class LotsaMonitors extends Thread {
-
-        /** How many recursions? Could cause Java stack overflow. */
-        static final int MAX_DEPTH = 800;
-
-        /** What is our depth? */
-        int depth = 0;
-
-        /** Thread ID */
-        int tid;
-
-        /** So output will have thread number. */
-        public LotsaMonitors(int tid, int depth) {
-            super("LotsaMonitors #" + new Integer(tid).toString());
-            this.tid = tid;
-            this.depth = depth;
-        }
-
-        /** Start a recursion that grabs monitors. */
-        public void run() {
-            System.out.println(">>>Starting " + this.toString() + " ...");
-            Thread.currentThread().yield();
-            this.recurse();
-            System.out.println("<<<Finished " + this.toString());
-        }
-
-        /** Every call to this method grabs an extra monitor. */
-        synchronized void recurse() {
-            if (this.depth > 0) {
-                new LotsaMonitors(tid, depth-1).recurse();
-            }
-        }
-    }
-
-    /**
-     * The test.
-     */
-    public static void main(String[] args) {
-        /* Start the two of these crazy threads. */
-        new LotsaMonitors(1, LotsaMonitors.MAX_DEPTH).start();
-        new LotsaMonitors(2, LotsaMonitors.MAX_DEPTH).start();
-
-        /* And sit there and GC for good measure. */
-        for (int i = 0; i < MAX_GC_ITERATIONS; i++) {
-            new LotsaMonitors(i+3, LotsaMonitors.MAX_DEPTH).start();
-            System.out.println(">>>Loading 10 classes and gc'ing ...");
-            Class[] classes = new Class[10];
-            fillClasses(classes);
-            classes = null;
-            System.gc();
-            Thread.currentThread().yield();
-            System.out.println("<<<Finished loading 10 classes and gc'ing");
-        }
-    }
-
-    /** How many times to GC? */
-    static final int MAX_GC_ITERATIONS = 10;
-
-    /** Load some classes into the array. */
-    static void fillClasses(Class[] classes) {
-        for (int i = 0; i < classes.length; i++) {
-            try {
-                classes[i] = Class.forName(classnames[i]);
-            } catch (ClassNotFoundException cnfe) {
-                cnfe.printStackTrace();
-            }
-        }
-    }
-
-    /** Some random classes to load. */
-    private static String[] classnames = {
-        "java.text.DecimalFormat",
-        "java.text.MessageFormat",
-        "java.util.GregorianCalendar",
-        "java.util.ResourceBundle",
-        "java.text.Collator",
-        "java.util.Date",
-        "java.io.Reader",
-        "java.io.Writer",
-        "java.lang.IllegalAccessException",
-        "java.lang.InstantiationException",
-        "java.lang.ClassNotFoundException",
-        "java.lang.CloneNotSupportedException",
-        "java.lang.InterruptedException",
-        "java.lang.NoSuchFieldException",
-        "java.lang.NoSuchMethodException",
-        "java.lang.RuntimeException",
-        "java.lang.ArithmeticException",
-        "java.lang.ArrayStoreException",
-        "java.lang.ClassCastException",
-        "java.lang.StringIndexOutOfBoundsException",
-        "java.lang.NegativeArraySizeException",
-        "java.lang.IllegalStateException",
-        "java.lang.IllegalArgumentException",
-        "java.lang.NumberFormatException",
-        "java.lang.IllegalThreadStateException",
-        "java.lang.IllegalMonitorStateException",
-        "java.lang.SecurityException",
-        "java.lang.ExceptionInInitializerError"
-    };
-
-}
--- a/test/jdk/vm/runtime/ReflectStackOverflow.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +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 4185411
- * @summary This program crashes in 1.1, but runs okay in 1.2.
- * @run main/othervm -Xss512k ReflectStackOverflow
- */
-import java.lang.reflect.*;
-
-public class ReflectStackOverflow {
-    private static final int COUNT = 11000;
-
-    public static void main(String[] cmdline) throws Throwable {
-        for (int i = 0; i < COUNT+1; i++) {
-            stuff(i);
-        }
-    }
-
-    private static void stuff(int count) throws Throwable {
-        if (count < COUNT)
-            return;  // don't do anything the first COUNT times.
-
-        try {
-            final Method method =
-                Method.class.getMethod
-                ("invoke", new Class[] { Object.class, Object[].class });
-
-            final Object[] args = new Object[] { method, null };
-            args[1] = args;
-
-            method.invoke(method, args); // "recursive reflection"
-            // exception should have been thrown by now...
-            System.out.println("how did I get here?");
-        } catch(Throwable t) {
-            int layers;
-            for(layers = 0; t instanceof InvocationTargetException; layers++)
-                t = ((InvocationTargetException)t).getTargetException();
-
-            System.err.println("Found " + layers + " layers of wrappers.");
-            if (!(t instanceof StackOverflowError)) {
-                throw t;
-            }
-        }
-    }
-}
--- a/test/jdk/vm/runtime/ShiftTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +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 4093292
- * @summary Test for correct code generation by the JIT
- */
-public class ShiftTest {
-    static final int w = 32;
-
-    private static void doTest(long ct) throws Exception {
-        int S22 = 0xc46cf7c2;
-        int S23 = 0xcfda9162;
-        int S24 = 0xd029aa4c;
-        int S25 = 0x17cf1801;
-        int A = (int)(ct & 0xffffffffL);
-        int B = (int)(ct >>> 32);
-        int x, y;
-        x = B - S25;
-        y = A & (w-1);
-        B = ((x >>> y) | (x << (w-y))) ^ A;
-        x = A - S24;
-        y = B & (w-1);
-        A = ((x >>> y) | (x << (w-y))) ^ B;
-        x = B - S23;
-        y = A & (w-1);
-        B = ((x >>> y) | (x << (w-y))) ^ A;
-        x = A - S22;
-        y = B & (w-1);
-        A = ((x >>> y) | (x << (w-y))) ^ B;
-        String astr = Integer.toHexString(A);
-        String bstr = Integer.toHexString(B);
-        System.err.println("A = " + astr + " B = " + bstr);
-        if ((!astr.equals("dcb38144")) ||
-            (!bstr.equals("1916de73"))) {
-            throw new RuntimeException("Unexpected shift results!");
-        }
-        System.err.println("Test passed");
-    }
-
-    public static void main(String[] args) throws Exception {
-        doTest(0x496def29b74be041L);
-    }
-}
--- a/test/jdk/vm/runtime/WideStrictInline.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +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 4169183
- * @summary Check for correct inlining by the interpreter (widefp and strictfp).
- *          The default is widefp.  A strictfp method was getting inlined
- *          into a widefp method.
- */
-
-import java.io.PrintStream;
-
-public class WideStrictInline {
-    static PrintStream out;
-    static float halfUlp;
-
-    static {
-        halfUlp = 1;
-        for ( int i = 127 - 24; i > 0; i-- )
-            halfUlp *= 2;
-    }
-
-    public static void main(String argv[]) throws Exception {
-        out = System.err;
-        pr(-1,"halfUlp",halfUlp);
-        WideStrictInline obj = new WideStrictInline();
-        for( int i=0; i<48; i++ )
-            obj.instanceMethod( i );
-    }
-
-    private static void pr(int i, String desc, float r) {
-        out.print(" i=("+i+") "+desc+" ; == "+r);
-        out.println(" , 0x"+Integer.toHexString(Float.floatToIntBits(r)));
-    }
-
-    private static strictfp float WideStrictInline(float par) {
-        return par;
-    }
-
-    public static strictfp float strictValue(int i) {
-        float r;
-        switch (i%4) {
-        case 0: r = -Float.MAX_VALUE;  break;
-        case 1: r =  Float.MAX_VALUE;  break;
-        case 2: r =  Float.MIN_VALUE;  break;
-        default : r = 1L << 24;
-        }
-        return r;
-    }
-
-    void instanceMethod (int i) throws Exception {
-        float r;
-        switch (i%4) {
-        case 0:
-            if (!Float.isInfinite( WideStrictInline(strictValue(i)*2) +
-                                   Float.MAX_VALUE ))
-                {
-                    pr(i,
-                       "WideStrictInline(-Float.MAX_VALUE * 2) " +
-                       "!= Float.NEGATIVE_INFINITY"
-                       ,WideStrictInline(strictValue(i)*2) + Float.MAX_VALUE);
-                }
-            r = WideStrictInline(strictValue(i)*2) + Float.MAX_VALUE;
-            if ( !Float.isInfinite( r ) ) {
-                pr(i,"r != Float.NEGATIVE_INFINITY",r);
-                throw new RuntimeException();
-            }
-            break;
-        case 1:
-            if (!Float.isInfinite(WideStrictInline(strictValue(i)+halfUlp) -
-                                  Float.MAX_VALUE )) {
-                pr(i,"WideStrictInline(Float.MAX_VALUE+halfUlp) " +
-                   "!= Float.POSITIVE_INFINITY"
-                   ,WideStrictInline(strictValue(i)+halfUlp) - Float.MAX_VALUE);
-            }
-            r = WideStrictInline(strictValue(i)+halfUlp) - Float.MAX_VALUE;
-            if ( !Float.isInfinite( r ) ) {
-                pr(i,"r != Float.POSITIVE_INFINITY",r);
-                throw new RuntimeException();
-            }
-            break;
-        case 2:
-            if (WideStrictInline(strictValue(i)/2) != 0) {
-                pr(i,"WideStrictInline(Float.MIN_VALUE/2) != 0",
-                   WideStrictInline(strictValue(i)/2));
-            }
-            r = WideStrictInline(strictValue(i)/2);
-            if ( r != 0 ) {
-                pr(i,"r != 0",r);
-                throw new RuntimeException();
-            }
-            break;
-        default:
-            if (WideStrictInline(strictValue(i)-0.5f) - strictValue(i) != 0) {
-                pr(i,"WideStrictInline(2^24-0.5) != 2^24",
-                   WideStrictInline(strictValue(i)-0.5f));
-            }
-            r = WideStrictInline(strictValue(i)-0.5f);
-            if ( r - strictValue(i) != 0 ) {
-                pr(i,"r != 2^24",r);
-                throw new RuntimeException();
-            }
-        }
-    }
-
-}
--- a/test/jdk/vm/verifier/TestStaticIF.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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 8007736
- * @summary Test static interface method.
- * @run main/othervm -Xverify:all TestStaticIF
- */
-
-public class TestStaticIF implements StaticMethodInInterface {
-
-    public static void main(String[] args) {
-        System.out.printf("main: %s%n", StaticMethodInInterface.get());
-    }
-}
-
-interface StaticMethodInInterface {
-
-    public static String get() {
-        return "Hello from StaticMethodInInterface.get()";
-    }
-}
--- a/test/jdk/vm/verifier/VerifyProtectedConstructor.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2007, 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 6490436
- * @summary Verify that protected constructor calls are not allowed for any classfile versions in either verifier.
- * @author Keith McGuigan
- */
-
-public class VerifyProtectedConstructor extends ClassLoader {
-  public static void main(String argv[]) throws Exception {
-    VerifyProtectedConstructor t = new VerifyProtectedConstructor();
-
-    t.loadSuperClass();
-
-    try {
-      t.checkClassVersion(49); // should not throw VerifyError
-      throw new Exception("FAIL: should be a VerifyError for CF version 49");
-    }
-    catch(VerifyError e) {
-       System.out.println("PASS for CF version 49");
-    }
-
-    try {
-      t.checkClassVersion(50); // should throw VerifyError
-      throw new Exception("FAIL: should be a VerifyError for CF version 50");
-    }
-    catch(VerifyError e) {
-       System.out.println("PASS");
-    }
-  }
-
-  private void loadSuperClass() {
-    /* -- code for super class A.A --
-       package A;
-       public class A {
-         protected A() {}
-       }
-    */
-    long[] cls_data = {
-      0xcafebabe00000032L, 0x000a0a0003000707L,
-      0x0008070009010006L, 0x3c696e69743e0100L,
-      0x0328295601000443L, 0x6f64650c00040005L,
-      0x010003412f410100L, 0x106a6176612f6c61L,
-      0x6e672f4f626a6563L, 0x7400210002000300L,
-      0x0000000001000400L, 0x0400050001000600L,
-      0x0000110001000100L, 0x0000052ab70001b1L,
-      0x0000000000000000L // 2 bytes extra
-    };
-    final int EXTRA = 2;
-    byte cf_bytes[] = toByteArray(cls_data);
-    defineClass("A.A", cf_bytes, 0, cf_bytes.length - EXTRA);
-  }
-
-  private int num_calls;
-  private static String classNames[] = { "B.B", "C.C" };
-
-  private void checkClassVersion(int version) throws VerifyError {
-    // This class is in violation of the spec since it accesses
-    // a protected constructor of a superclass while not being in the
-    // same package.
-    /* -- code for test class --
-        package B;
-        public class B extends A.A {
-          public static void f() { new A.A(); }
-        }
-    */
-    long[] cls_data = {
-      0xcafebabe00000032L, 0x000b0a0002000807L,
-      0x000907000a010006L, 0x3c696e69743e0100L,
-      0x0328295601000443L, 0x6f6465010001660cL,
-      0x0004000501000341L, 0x2f41010003422f42L,
-      0x0021000300020000L, 0x0000000200010004L,
-      0x0005000100060000L, 0x0011000100010000L,
-      0x00052ab70001b100L, 0x0000000009000700L,
-      0x0500010006000000L, 0x1500020000000000L,
-      0x09bb000259b70001L, 0x57b1000000000000L // no extra bytes
-    };
-    final int EXTRA = 0;
-
-    byte cf_bytes[] = toByteArray(cls_data);
-
-    // set version
-    cf_bytes[7] = (byte)version;
-
-    // Change B.B to C.C, D.D, ... for subsequent calls so we can call this
-    // multiple times and define different classes.
-    cf_bytes[61] += num_calls;
-    cf_bytes[63] += num_calls;
-    String name = classNames[num_calls];
-    num_calls++;
-
-    Class c = defineClass(name, cf_bytes, 0, cf_bytes.length - EXTRA);
-
-    try { c.newInstance(); } // to force linking, thus verification
-    catch(InstantiationException e) {}
-    catch(IllegalAccessException e) {}
-  }
-
-  static private byte[] toByteArray(long arr[]) {
-    // convert long array to byte array
-    java.nio.ByteBuffer bbuf = java.nio.ByteBuffer.allocate(arr.length * 8);
-    bbuf.asLongBuffer().put(java.nio.LongBuffer.wrap(arr));
-    return bbuf.array();
-  }
-}
--- a/test/jdk/vm/verifier/VerifyStackForExceptionHandlers.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2007, 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 6547378
- * @summary Verify that methods with max_stack==0 don't have exception handlers
- * @author Keith McGuigan
- */
-
-public class VerifyStackForExceptionHandlers extends ClassLoader {
-    public static void main(String argv[]) throws Exception {
-        VerifyStackForExceptionHandlers t =
-            new VerifyStackForExceptionHandlers();
-
-        try {
-            t.loadGoodClass();
-        } catch(VerifyError e) {
-            throw new Exception("FAIL: should be no VerifyError for class A");
-        }
-
-        try {
-            t.loadBadClass();
-            throw new Exception("FAIL: should be a VerifyError for class B");
-        } catch(VerifyError e) {
-            System.out.println("PASS");
-        }
-    }
-
-    private void loadGoodClass() {
-        /* -- code for class A --
-           public class A {
-               public static void f() {}
-           }
-        */
-        long[] cls_data = {
-            0xcafebabe00000031L, 0x000e0a0003000b07L,
-            0x000c07000d010006L, 0x3c696e69743e0100L,
-            0x0328295601000443L, 0x6f646501000f4c69L,
-            0x6e654e756d626572L, 0x5461626c65010001L,
-            0x6601000a536f7572L, 0x636546696c650100L,
-            0x06412e6a6176610cL, 0x0004000501000141L,
-            0x0100106a6176612fL, 0x6c616e672f4f626aL,
-            0x6563740021000200L, 0x0300000000000200L,
-            0x0100040005000100L, 0x060000001d000100L,
-            0x01000000052ab700L, 0x01b1000000010007L,
-            0x0000000600010000L, 0x0001000900080005L,
-            0x0001000600000019L, 0x0000000000000001L,
-            0xb100000001000700L, 0x0000060001000000L,
-            0x0200010009000000L, 0x02000a0000000000L
-        };
-        final int EXTRA = 5;
-
-        byte cf_bytes[] = toByteArray(cls_data);
-        Class c = defineClass("A", cf_bytes, 0, cf_bytes.length - EXTRA);
-
-        try { c.newInstance(); } // to force linking, thus verification
-        catch(InstantiationException e) {}
-        catch(IllegalAccessException e) {}
-    }
-
-    private void loadBadClass() throws VerifyError {
-        /* -- code for class B --
-           public class B {
-               public static void g() {}
-               public static void f() {
-                  // bytecode modified to have a max_stack value of 0
-                  try { g(); }
-                  catch (NullPointerException e) {}
-               }
-        }
-        */
-        long[] cls_data = {
-            0xcafebabe00000031L, 0x00120a000400060aL,
-            0x000d00030c000f00L, 0x0a0700050100106aL,
-            0x6176612f6c616e67L, 0x2f4f626a6563740cL,
-            0x0011000a01000a53L, 0x6f7572636546696cL,
-            0x6507000901001e6aL, 0x6176612f6c616e67L,
-            0x2f4e756c6c506f69L, 0x6e74657245786365L,
-            0x7074696f6e010003L, 0x282956010006422eL,
-            0x6a61736d01000443L, 0x6f646507000e0100L,
-            0x0142010001670100L, 0x01660100063c696eL,
-            0x69743e0021000d00L, 0x0400000000000300L,
-            0x010011000a000100L, 0x0c00000011000100L,
-            0x01000000052ab700L, 0x01b1000000000009L,
-            0x000f000a0001000cL, 0x0000000d00000000L,
-            0x00000001b1000000L, 0x0000090010000a00L,
-            0x01000c0000001c00L, 0x00000100000008b8L,
-            0x0002a700044bb100L, 0x0100000003000600L,
-            0x0800000001000700L, 0x000002000b000000L // 3 bytes extra
-
-        };
-        final int EXTRA = 3;
-
-        byte cf_bytes[] = toByteArray(cls_data);
-        Class c = defineClass("B", cf_bytes, 0, cf_bytes.length - EXTRA);
-
-        try { c.newInstance(); } // to force linking, thus verification
-        catch(InstantiationException e) {}
-        catch(IllegalAccessException e) {}
-    }
-
-    static private byte[] toByteArray(long arr[]) {
-        // convert long array to byte array
-        java.nio.ByteBuffer bbuf = java.nio.ByteBuffer.allocate(arr.length * 8);
-        bbuf.asLongBuffer().put(java.nio.LongBuffer.wrap(arr));
-        return bbuf.array();
-    }
-    }
--- a/test/jdk/vm/verifier/defaultMethods/DefaultMethodRegressionTests.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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 8003639
- * @summary defaultMethod resolution and verification
- * @run main DefaultMethodRegressionTests
- */
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * This set of classes/interfaces (K/I/C) is specially designed to expose a
- * bug in the JVM where it did not find some overloaded methods in some
- * specific situations. (fixed by hotspot changeset ffb9316fd9ed).
- */
-interface K {
-    int bbb(Long l);
-}
-
-interface I extends K {
-    default void aaa() {}
-    default void aab() {}
-    default void aac() {}
-
-    default int bbb(Integer i) { return 22; }
-    default int bbb(Float f) { return 33; }
-    default int bbb(Long l) { return 44; }
-    default int bbb(Double d) { return 55; }
-    default int bbb(String s) { return 66; }
-
-    default void caa() {}
-    default void cab() {}
-    default void cac() {}
-}
-
-class C implements I {}
-
-public class DefaultMethodRegressionTests {
-    public static void main(String... args) {
-        new DefaultMethodRegressionTests().run(args);
-    }
-    void run(String... args) {
-        testLostOverloadedMethod();
-        System.out.println("testLostOverloadedMethod: OK");
-        testInferenceVerifier();
-        System.out.println("testInferenceVerifier: OK");
-    }
-    void testLostOverloadedMethod() {
-        C c = new C();
-        assertEquals(c.bbb(new Integer(1)), 22);
-        assertEquals(c.bbb(new Float(1.1)), 33);
-        assertEquals(c.bbb(new Long(1L)), 44);
-        assertEquals(c.bbb(new Double(0.01)), 55);
-        assertEquals(c.bbb(new String("")), 66);
-    }
-    // Test to ensure that the inference verifier accepts older classfiles
-    // with classes that implement interfaces with defaults.
-    void testInferenceVerifier() {
-        // interface I { int m() default { return 99; } }
-        byte I_bytes[] = {
-            (byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, 0x00, 0x00, 0x00, 0x34,
-            0x00, 0x08, 0x07, 0x00, 0x06, 0x07, 0x00, 0x07,
-            0x01, 0x00, 0x03, 0x66, 0x6f, 0x6f, 0x01, 0x00,
-            0x03, 0x28, 0x29, 0x49, 0x01, 0x00, 0x04, 0x43,
-            0x6f, 0x64, 0x65, 0x01, 0x00, 0x01, 0x49, 0x01,
-            0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c,
-            0x61, 0x6e, 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65,
-            0x63, 0x74, 0x06, 0x00, 0x00, 0x01, 0x00, 0x02,
-            0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01,
-            0x00, 0x03, 0x00, 0x04, 0x00, 0x01, 0x00, 0x05,
-            0x00, 0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0x01,
-            0x00, 0x00, 0x00, 0x03, 0x10, 0x63, (byte)0xac, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00
-        };
-        // public class C implements I {}  /* -target 1.5 */
-        byte C_bytes[] = {
-            (byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, 0x00, 0x00, 0x00, 0x31,
-            0x00, 0x0c, 0x0a, 0x00, 0x03, 0x00, 0x08, 0x07,
-            0x00, 0x09, 0x07, 0x00, 0x0a, 0x07, 0x00, 0x0b,
-            0x01, 0x00, 0x06, 0x3c, 0x69, 0x6e, 0x69, 0x74,
-            0x3e, 0x01, 0x00, 0x03, 0x28, 0x29, 0x56, 0x01,
-            0x00, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x0c, 0x00,
-            0x05, 0x00, 0x06, 0x01, 0x00, 0x01, 0x43, 0x01,
-            0x00, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c,
-            0x61, 0x6e, 0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65,
-            0x63, 0x74, 0x01, 0x00, 0x01, 0x49, 0x00, 0x21,
-            0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04,
-            0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x05,
-            0x00, 0x06, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00,
-            0x00, 0x11, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
-            0x00, 0x05, 0x2a, (byte)0xb7, 0x00, 0x01, (byte)0xb1, 0x00,
-            0x00, 0x00, 0x00, 0x00, 0x00
-        };
-
-        ClassLoader cl = new ClassLoader() {
-            protected Class<?> findClass(String name) {
-                if (name.equals("I")) {
-                    return defineClass("I", I_bytes, 0, I_bytes.length);
-                } else if (name.equals("C")) {
-                    return defineClass("C", C_bytes, 0, C_bytes.length);
-                } else {
-                    return null;
-                }
-            }
-        };
-        try {
-            Class.forName("C", true, cl);
-        } catch (Exception e) {
-            // unmodified verifier will throw VerifyError
-            throw new RuntimeException(e);
-        }
-    }
-    void assertEquals(Object o1, Object o2) {
-        System.out.print("Expected: " + o1);
-        System.out.println(", Obtained: " + o2);
-        if (!o1.equals(o2)) {
-            throw new RuntimeException("got unexpected values");
-        }
-    }
-}
--- a/test/jdk/vm/verifier/defaultMethods/DefaultMethodRegressionTestsRun.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2013, 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 8003639
- * @summary defaultMethod resolution and verification using an URLClassLoader
- * @modules jdk.compiler
- *          jdk.zipfs
- * @compile -XDignore.symbol.file=true DefaultMethodRegressionTestsRun.java
- * @run main DefaultMethodRegressionTestsRun
- */
-import java.io.File;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-/**
- * This test is a variant of DefaultMethodRegressionTests, this one creates
- * an URLClassLoader to load the support classes.
- *
- */
-public class DefaultMethodRegressionTestsRun {
-    public static void main(String... args) throws Exception {
-        File scratchDir = new File(".");
-        File testDir = new File(scratchDir, "testdir");
-        testDir.mkdirs();
-        File srcFile = new File(new File(System.getProperty("test.src")),
-                "DefaultMethodRegressionTests.java");
-        String[] javacargs = {
-            srcFile.getAbsolutePath(),
-            "-d",
-            testDir.getAbsolutePath()
-        };
-        com.sun.tools.javac.Main.compile(javacargs);
-        runClass(testDir, "DefaultMethodRegressionTests");
-    }
-    static void runClass(
-            File classPath,
-            String classname) throws Exception {
-        URL[] urls = {classPath.toURI().toURL()};
-        ClassLoader loader = new URLClassLoader(urls);
-        Class<?> c = loader.loadClass(classname);
-
-        Class<?>[] argTypes = new Class<?>[]{String[].class};
-        Object[] methodArgs = new Object[]{null};
-
-        Method method = c.getMethod("main", argTypes);
-        method.invoke(c, methodArgs);
-    }
-}
--- a/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/InheritDocForUserTags/DocTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,8 @@
  * @run main DocTest
  */
 
+import javadoc.tester.JavadocTester;
+
 /**
  * DocTest documentation.
  *
@@ -39,8 +41,6 @@
  * @implSpec DocTest implementation spec.
  * @implNote DocTest implementation note.
  */
-import javadoc.tester.JavadocTester;
-
 public class DocTest extends JavadocTester {
     public static void main(String... args) throws Exception {
         DocTest tester = new DocTest();
@@ -51,6 +51,7 @@
     public void test() {
         javadoc("-verbose",
                 "-d", "DocTest",
+                "-sourcepath", System.getProperty("test.src.path"),
                 "-tag", "apiNote:optcm:<em>API Note</em>",
                 "-tag", "implSpec:optcm:<em>Implementation Requirements</em>:",
                 "-tag", "implNote:optcm:<em>Implementation Note</em>:",
--- a/test/langtools/jdk/javadoc/doclet/MetaTag/MetaTag.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/MetaTag/MetaTag.java	Tue Mar 26 09:05:10 2019 -0400
@@ -93,14 +93,19 @@
                 "<meta name=\"keywords\" content=\"Overview, Sample Packages\">");
 
         // NOTE: Hopefully, this regression test is not run at midnight.  If the output
-        // was generated yesterday and this test is run today, the test will fail.
-        checkOutput("overview-summary.html", found,
-                "<meta name=\"" + metaNameDate + "\" content=\"" + date() + "\">");
+        // was generated yesterday and this test is run today, this check could fail ...
+        // so make sure the date has not changed since the test started
+        String date = date();
+        if (date.equals(startDate)) {
+            checkOutput("overview-summary.html", found,
+                    "<meta name=\"" + metaNameDate + "\" content=\"" + date + "\">");
+        }
     }
 
     private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+    private static final String startDate = date();
 
-    String date() {
+    static String date() {
         return dateFormat.format(new Date());
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testAutoLoadTaglets/TestAutoLoadTaglets.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8219958
+ * @summary Automatically load taglets from a jar file
+ * @library /tools/lib ../../lib
+ * @modules
+ *     jdk.javadoc/jdk.javadoc.internal.tool
+ *     jdk.compiler/com.sun.tools.javac.api
+ *     jdk.compiler/com.sun.tools.javac.main
+ * @build javadoc.tester.* toolbox.ToolBox builder.ClassBuilder toolbox.JarTask
+ * @run main/othervm TestAutoLoadTaglets
+ */
+
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import builder.ClassBuilder;
+import toolbox.JarTask;
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
+import javadoc.tester.JavadocTester;
+
+public class TestAutoLoadTaglets extends JavadocTester {
+
+    final ToolBox tb;
+
+    public static void main(String... args) throws Exception {
+        TestAutoLoadTaglets tester = new TestAutoLoadTaglets();
+        tester.runTests(m -> new Object[]{Paths.get(m.getName())});
+    }
+
+    TestAutoLoadTaglets() {
+        tb = new ToolBox();
+    }
+
+    @Test
+    public void test(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        Path outDir = base.resolve("out");
+
+        createTagletsJar(base, srcDir);
+
+        new ClassBuilder(tb, "pkg.A")
+                .setComments("test {@taglet1} and {@taglet2}")
+                .setModifiers("public", "class")
+                .write(srcDir);
+
+        javadoc("-d", outDir.toString(),
+                "-sourcepath", srcDir.toString(),
+                "-tagletpath", "taglets.jar",
+                "pkg");
+
+        checkExit(Exit.OK);
+
+        checkOutput("pkg/A.html", true,
+                "test user taglet taglet1 and user taglet taglet2");
+    }
+
+    private void createTagletsJar(Path base, Path srcDir) throws Exception {
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+        createTaglets(srcDir);
+
+        new JavacTask(tb).files(srcDir.resolve("Taglet1.java"), srcDir.resolve("Taglet2.java"))
+                .outdir(classes).run();
+
+        Path services = classes.resolve("META-INF").resolve("services").resolve("jdk.javadoc.doclet.Taglet");
+        tb.writeFile(services,
+                "Taglet1\n"
+                + "Taglet2");
+
+        new JarTask(tb, srcDir).run("cf", "taglets.jar", "-C", classes.toString(), ".");
+    }
+
+    private void createTaglets(Path srcDir) throws Exception {
+        for (int i = 1; i < 3; i++) {
+            tb.writeJavaFiles(srcDir,
+                    "import com.sun.source.doctree.DocTree;\n"
+                    + "import jdk.javadoc.doclet.Taglet;\n"
+                    + "import javax.lang.model.element.Element;\n"
+                    + "import java.util.List;\n"
+                    + "import java.util.Set;\n"
+                    + "public class Taglet" + i + " implements Taglet {\n"
+                    + "    @Override\n"
+                    + "    public Set<Location> getAllowedLocations() {\n"
+                    + "        return null;\n"
+                    + "    }\n"
+                    + "    @Override\n"
+                    + "    public boolean isInlineTag() {\n"
+                    + "        return true;\n"
+                    + "    }\n"
+                    + "    @Override\n"
+                    + "    public String getName() {\n"
+                    + "        return \"taglet" + i + "\";\n"
+                    + "    }\n"
+                    + "    @Override\n"
+                    + "    public String toString(List<? extends DocTree> tags, Element "
+                    + "element) {\n"
+                    + "        return \"user taglet taglet" + i + "\";\n"
+                    + "    }\n"
+                    + "}\n");
+        }
+    }
+
+}
--- a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java	Tue Mar 26 09:05:10 2019 -0400
@@ -215,17 +215,21 @@
                 "<div class=\"deprecatedSummary\">\n"
                 + "<table>\n"
                 + "<caption><span>For Removal</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Element</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>",
+                + "</tr>\n"
+                + "</thead>",
                 "<div class=\"deprecatedSummary\">\n"
                 + "<table>\n"
                 + "<caption><span>Enums</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Enum</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\">\n"
                 + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"pkg/TestEnum.html\" title=\"enum in pkg\">pkg.TestEnum</a></th>\n"
@@ -239,10 +243,12 @@
                 "<div class=\"deprecatedSummary\">\n"
                 + "<table>\n"
                 + "<caption><span>Exceptions</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Exceptions</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\">\n"
                 + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"pkg/TestException.html\" title=\"class in pkg\">pkg.TestException</a></th>\n"
@@ -256,10 +262,12 @@
                 "<div class=\"deprecatedSummary\">\n"
                 + "<table>\n"
                 + "<caption><span>Fields</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Field</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\">\n"
                 + "<th class=\"colDeprecatedItemName\" scope=\"row\"><a href=\"pkg/DeprecatedClassByAnnotation.html#field\">pkg.DeprecatedClassByAnnotation.field</a></th>\n"
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Tue Mar 26 09:05:10 2019 -0400
@@ -252,10 +252,13 @@
         checkExit(Exit.OK);
         checkOutput("pkg2/Test.html", false, "<h2>Property Summary</h2>");
         checkOutput("pkg2/Test.html", true,
-                "<th class=\"colFirst\" scope=\"col\">Modifier and Type</th>\n"
+                "<thead>\n"
+                + "<tr>\n"
+                + "<th class=\"colFirst\" scope=\"col\">Modifier and Type</th>\n"
                 + "<th class=\"colSecond\" scope=\"col\">Method</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\" id=\"i0\">\n"
                 + "<td class=\"colFirst\"><code>&lt;T&gt;&nbsp;java.lang.Object</code></td>\n"
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestIndirectExportsOpens.java	Tue Mar 26 09:05:10 2019 -0400
@@ -193,10 +193,12 @@
                 "<div class=\"packagesSummary\">\n"
                 + "<table>\n"
                 + "<caption><span>" + typeString + "</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">From</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Packages</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\">\n"
                 + "<th class=\"colFirst\" scope=\"row\"><a href=\"../m/module-summary.html\">m</a></th>\n"
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServices.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModuleServices.java	Tue Mar 26 09:05:10 2019 -0400
@@ -199,10 +199,12 @@
         checkOutput("m/module-summary.html", true,
                 "<div class=\"usesSummary\">\n<table>\n" +
                 "<caption><span>Uses</span><span class=\"tabEnd\">&nbsp;</span></caption>\n" +
+                "<thead>\n" +
                 "<tr>\n" +
                 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" +
                 "<th class=\"colLast\" scope=\"col\">Description</th>\n" +
                 "</tr>\n" +
+                "</thead>\n" +
                 "<tbody>\n" +
                 "<tr class=\"altColor\">\n" +
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"class in p1\">A</a></th>\n" +
@@ -240,10 +242,12 @@
         checkOutput("m/module-summary.html", true,
                 "<div class=\"usesSummary\">\n<table>\n" +
                 "<caption><span>Uses</span><span class=\"tabEnd\">&nbsp;</span></caption>\n" +
+                "<thead>\n" +
                 "<tr>\n" +
                 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" +
                 "<th class=\"colLast\" scope=\"col\">Description</th>\n" +
                 "</tr>\n" +
+                "</thead>\n" +
                 "<tbody>\n" +
                 "<tr class=\"altColor\">\n" +
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"class in p1\">A</a></th>\n" +
@@ -307,10 +311,12 @@
         checkOutput("m/module-summary.html", true,
                 "<div class=\"providesSummary\">\n<table>\n" +
                 "<caption><span>Provides</span><span class=\"tabEnd\">&nbsp;</span></caption>\n" +
+                "<thead>\n" +
                 "<tr>\n" +
                 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" +
                 "<th class=\"colLast\" scope=\"col\">Description</th>\n" +
                 "</tr>\n" +
+                "</thead>\n" +
                 "<tbody>\n" +
                 "<tr class=\"altColor\">\n" +
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"interface in p1\">A</a></th>\n" +
@@ -351,10 +357,12 @@
         checkOutput("m/module-summary.html", true,
                 "<div class=\"providesSummary\">\n<table>\n" +
                 "<caption><span>Provides</span><span class=\"tabEnd\">&nbsp;</span></caption>\n" +
+                "<thead>\n" +
                 "<tr>\n" +
                 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" +
                 "<th class=\"colLast\" scope=\"col\">Description</th>\n" +
                 "</tr>\n" +
+                "</thead>\n" +
                 "<tbody>\n" +
                 "<tr class=\"altColor\">\n" +
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"interface in p1\">A</a></th>\n" +
@@ -394,10 +402,12 @@
         checkOutput("m/module-summary.html", true,
                 "<div class=\"providesSummary\">\n<table>\n" +
                 "<caption><span>Provides</span><span class=\"tabEnd\">&nbsp;</span></caption>\n" +
+                "<thead>\n" +
                 "<tr>\n" +
                 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" +
                 "<th class=\"colLast\" scope=\"col\">Description</th>\n" +
                 "</tr>\n" +
+                "</thead>\n" +
                 "<tbody>\n" +
                 "<tr class=\"altColor\">\n" +
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"p1/A.html\" title=\"interface in p1\">A</a></th>\n" +
@@ -408,10 +418,12 @@
                 "</table>",
                 "<div class=\"usesSummary\">\n<table>\n" +
                 "<caption><span>Uses</span><span class=\"tabEnd\">&nbsp;</span></caption>\n" +
+                "<thead>\n" +
                 "<tr>\n" +
                 "<th class=\"colFirst\" scope=\"col\">Type</th>\n" +
                 "<th class=\"colLast\" scope=\"col\">Description</th>\n" +
                 "</tr>\n" +
+                "</thead>\n" +
                 "<tbody>\n" +
                 "<tr class=\"altColor\">\n" +
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"p2/B.html\" title=\"class in p2\">B</a></th>\n" +
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java	Tue Mar 26 09:05:10 2019 -0400
@@ -623,18 +623,22 @@
                 "<div class=\"overviewSummary\">\n"
                 + "<table summary=\"Module Summary table, listing modules, and an explanation\">\n"
                 + "<caption><span>Modules</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Module</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>");
+                + "</tr>\n"
+                + "</thead>");
         checkOutput("overview-summary.html", false,
                 "<div class=\"overviewSummary\">\n"
                 + "<table summary=\"Package Summary table, listing packages, and an explanation\">\n"
                 + "<caption><span>Packages</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>");
+                + "</tr>\n"
+                + "</thead>");
     }
 
     void checkOverviewSummaryPackages() {
@@ -642,10 +646,12 @@
                 "<div class=\"overviewSummary\">\n"
                 + "<table summary=\"Module Summary table, listing modules, and an explanation\">\n"
                 + "<caption><span>Modules</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Module</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>",
+                + "</tr>\n"
+                + "</thead>",
                 "</table>\n"
                 + "</div>\n"
                 + "<div class=\"contentContainer\">\n"
@@ -659,10 +665,12 @@
                 "<div class=\"overviewSummary\">\n"
                 + "<table summary=\"Package Summary table, listing packages, and an explanation\">\n"
                 + "<caption><span>Packages</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>",
+                + "</tr>\n"
+                + "</thead>\n",
                 "</script>\n"
                 + "<div class=\"contentContainer\">\n"
                 + "<div class=\"block\">The overview summary page header.</div>\n"
@@ -678,18 +686,22 @@
                 "<div class=\"overviewSummary\">\n"
                 + "<table>\n"
                 + "<caption><span>Modules</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Module</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>");
+                + "</tr>\n"
+                + "</thead>");
         checkOutput("overview-summary.html", false,
                 "<div class=\"overviewSummary\">\n"
                 + "<table>\n"
                 + "<caption><span>Packages</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>");
+                + "</tr>\n"
+                + "</thead>");
     }
 
     void checkHtml5OverviewSummaryPackages() {
@@ -697,10 +709,12 @@
                 "<div class=\"overviewSummary\">\n"
                 + "<table>\n"
                 + "<caption><span>Modules</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Module</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>",
+                + "</tr>\n"
+                + "</thead>",
                 "</table>\n"
                 + "</div>\n"
                 + "</main>\n"
@@ -717,10 +731,12 @@
         checkOutput("overview-summary.html", true,
                 "<div class=\"overviewSummary\">\n<table>\n"
                 + "<caption><span>Packages</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>",
+                + "</tr>\n"
+                + "</thead>",
                 "</script>\n"
                 + "</nav>\n"
                 + "</header>\n"
@@ -788,20 +804,26 @@
                 + "<div class=\"block\">With a test description for uses.</div>\n</td>\n"
                 + "</tr>",
                 "<caption><span>Opens</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>",
+                + "</tr>\n"
+                + "</thead>",
                 "<caption><span>Uses</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Type</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>",
+                + "</tr>\n"
+                + "</thead>",
                 "<caption><span>Provides</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Type</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>");
+                + "</tr>\n"
+                + "</thead>");
     }
 
     void checkAggregatorModuleSummary() {
@@ -978,18 +1000,21 @@
                 + "</td>",
                 "<div class=\"requiresSummary\">\n<table>\n"
                 + "<caption><span>Requires</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Modifier</th>\n"
                 + "<th class=\"colSecond\" scope=\"col\">Module</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>",
                 "<div class=\"requiresSummary\">\n<table>\n"
                 + "<caption><span>Indirect Requires</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Modifier</th>\n"
                 + "<th class=\"colSecond\" scope=\"col\">Module</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>",
                 "<div class=\"packagesSummary\">\n<table>\n"
                 + "<caption><span>Indirect Opens</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">From</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Packages</th>\n"
@@ -1011,10 +1036,12 @@
                 + "<td class=\"colLast\">&nbsp;</td>",
                 "<div class=\"packagesSummary\">\n<table>\n"
                 + "<caption><span>Opens</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\" id=\"i0\">\n"
                 + "<th class=\"colFirst\" scope=\"row\"><a href=\"testpkgmdlB/package-summary.html\">testpkgmdlB</a></th>\n"
@@ -1081,11 +1108,13 @@
                 + " class=\"tableTab\" onclick=\"show(2);\">Opens</button></div>");
         checkOutput("moduleC/module-summary.html", found,
                 "<caption><span>Exports</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colSecond\" scope=\"col\">Exported To Modules</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>");
+                + "</tr>\n"
+                + "</thead>");
         checkOutput("moduletags/module-summary.html", true,
                 "<th class=\"colFirst\" scope=\"row\"><a href=\"testpkgmdltags/package-summary.html\">testpkgmdltags</a></th>\n"
                 + "<td class=\"colLast\">&nbsp;</td>");
@@ -1301,16 +1330,20 @@
                 + " onclick=\"show(2);\">Class Summary</button><button role=\"tab\" aria-selected=\"false\""
                 + " aria-controls=\"typeSummary_tabpanel\" tabindex=\"-1\" onkeydown=\"switchTab(event)\""
                 + " id=\"t6\" class=\"tableTab\" onclick=\"show(32);\">Annotation Types Summary</button></div>\n",
-                "<tr>\n"
+                "<thead>\n"
+                + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Class</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>");
+                + "</tr>\n"
+                + "</thead>\n");
         checkOutput("allpackages-index.html", true,
                 "<caption><span>Package Summary</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>\n");
+                + "</tr>\n"
+                + "</thead>");
         checkOutput("allclasses-index.html", found,
                 "<table aria-labelledby=\"t0\">\n");
         checkOutput("allpackages-index.html", found,
--- a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java	Tue Mar 26 09:05:10 2019 -0400
@@ -426,11 +426,13 @@
                 + "type <a href=\"../Foo4.html\" title=\"class in "
                 + "pkg2\">Foo4</a></span><span class=\"tabEnd\">&nbsp;"
                 + "</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Modifier and Type</th>\n"
                 + "<th class=\"colSecond\" scope=\"col\">Method</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\">\n"
                 + "<td class=\"colFirst\"><code>void</code></td>\n"
--- a/test/langtools/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testPackagePage/TestPackagePage.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,17 +87,21 @@
         checkOutput("allclasses-index.html", true,
                 "<div class=\"typeSummary\">\n<table>\n"
                 + "<caption><span>Class Summary</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Class</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>\n");
+                + "</tr>\n"
+                + "</thead>\n");
         checkOutput("allpackages-index.html", true,
                 "<div class=\"packagesSummary\">\n<table>\n"
                 + "<caption><span>Package Summary</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
-                + "</tr>\n");
+                + "</tr>\n"
+                + "</thead>\n");
         checkOutput("type-search-index.js", true,
                 "{\"l\":\"All Classes\",\"url\":\"allclasses-index.html\"}");
         checkOutput("package-search-index.js", true,
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Tue Mar 26 09:05:10 2019 -0400
@@ -717,6 +717,7 @@
                 + " id=\"t6\" class=\"tableTab\" onclick=\"show(32);\">Annotation Types Summary</button></div>\n"
                 + "<div id=\"typeSummary_tabpanel\" role=\"tabpanel\">\n"
                 + "<table aria-labelledby=\"t0\">\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Class</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
@@ -726,6 +727,7 @@
         checkOutput("allpackages-index.html", true,
                 "<div class=\"packagesSummary\">\n<table>\n"
                 + "<caption><span>Package Summary</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
--- a/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/doclet/testUnnamedPackage/TestUnnamedPackage.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,10 +69,12 @@
         checkOutput("allclasses-index.html", true,
                 "<div class=\"typeSummary\">\n<table>\n"
                 + "<caption><span>Class Summary</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Class</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\" id=\"i0\">\n"
                 + "<td class=\"colFirst\"><a href=\"C.html\" title=\"class in &lt;Unnamed&gt;\">C</a></td>\n"
@@ -86,10 +88,12 @@
         checkOutput("allpackages-index.html", true,
                 "<div class=\"packagesSummary\">\n<table>\n"
                 + "<caption><span>Package Summary</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<thead>\n"
                 + "<tr>\n"
                 + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>\n"
+                + "</thead>\n"
                 + "<tbody>\n"
                 + "<tr class=\"altColor\">\n"
                 + "<th class=\"colFirst\" scope=\"row\"><a href=\"package-summary.html\">&lt;Unnamed&gt;</a></th>\n"
--- a/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/jdk/javadoc/lib/javadoc/tester/JavadocTester.java	Tue Mar 26 09:05:10 2019 -0400
@@ -96,7 +96,7 @@
  *      }
  *
  *      // test methods...
- *      @Test
+ *      {@literal @}Test
  *      void test() {
  *          javadoc(<i>args</i>);
  *          checkExit(Exit.OK);
--- a/test/langtools/jdk/javadoc/tool/doclint/ImplicitHeadersTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2013, 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 8006346
- * @summary doclint should make allowance for headers generated by standard doclet
- * @modules jdk.javadoc/jdk.javadoc.internal.tool
- */
-
-import java.io.File;
-
-/**
- * <h3> Header </h3>
- */
-public class ImplicitHeadersTest {
-    public static void main(String... args) {
-        File testSrc = new File(System.getProperty("test.src"));
-        File testFile = new File(testSrc, ImplicitHeadersTest.class.getSimpleName() + ".java");
-        String[] javadocArgs = { "-d", "out", testFile.getPath() };
-        int rc = jdk.javadoc.internal.tool.Main.execute(javadocArgs);
-        if (rc != 0)
-            throw new Error("unexpected exit: rc=" + rc);
-    }
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/tool/doclint/ImplicitHeadingsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8006346
+ * @summary doclint should make allowance for headings generated by standard doclet
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ */
+
+import java.io.File;
+
+/**
+ * <h2> Class heading </h2>
+ */
+public class ImplicitHeadingsTest {
+    /**
+     * <h4>Method heading</h4>
+     * @param args command-line args
+     */
+    public static void main(String... args) {
+        File testSrc = new File(System.getProperty("test.src"));
+        File testFile = new File(testSrc, ImplicitHeadingsTest.class.getSimpleName() + ".java");
+        String[] javadocArgs = { "-d", "out", testFile.getPath() };
+        int rc = jdk.javadoc.internal.tool.Main.execute(javadocArgs);
+        if (rc != 0)
+            throw new Error("unexpected exit: rc=" + rc);
+    }
+}
+
--- a/test/langtools/tools/doclint/AccessibilityTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/doclint/AccessibilityTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -10,17 +10,37 @@
 
 /** */
 public class AccessibilityTest {
+    /**
+     * <h1> ... </h1>
+     */
+    public class Bad_H1 { }
+
+    /**
+     * <h3> ... </h3>
+     */
+    public class Missing_H2 { }
+
+    /**
+     * <h2> ... </h2>
+     * <h4> ... </h4>
+     */
+    public class Missing_H3 { }
 
     /**
      * <h2> ... </h2>
      */
-    public void missing_h1() { }
+    public void bad_h2() { }
 
     /**
-     * <h1> ... </h1>
+     * <h4> ... </h4>
+     */
+    public void missing_h3() { }
+
+    /**
      * <h3> ... </h3>
+     * <h5> ... </h5>
      */
-    public void missing_h2() { }
+    public void missing_h4() { }
 
     /**
      * <img src="x.jpg">
--- a/test/langtools/tools/doclint/AccessibilityTest.out	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/doclint/AccessibilityTest.out	Tue Mar 26 09:05:10 2019 -0400
@@ -1,13 +1,25 @@
-AccessibilityTest.java:15: error: header used out of sequence: <H2>
-     * <h2> ... </h2>
+AccessibilityTest.java:14: error: unexpected heading used: <H1>, compared to implicit preceding heading: <H1>
+     * <h1> ... </h1>
        ^
-AccessibilityTest.java:21: error: header used out of sequence: <H3>
+AccessibilityTest.java:19: error: heading used out of sequence: <H3>, compared to implicit preceding heading: <H1>
      * <h3> ... </h3>
        ^
-AccessibilityTest.java:26: error: no "alt" attribute for image
+AccessibilityTest.java:25: error: heading used out of sequence: <H4>, compared to previous heading: <H2>
+     * <h4> ... </h4>
+       ^
+AccessibilityTest.java:30: error: unexpected heading used: <H2>, compared to implicit preceding heading: <H3>
+     * <h2> ... </h2>
+       ^
+AccessibilityTest.java:40: error: unexpected heading used: <H3>, compared to implicit preceding heading: <H3>
+     * <h3> ... </h3>
+       ^
+AccessibilityTest.java:41: error: heading used out of sequence: <H5>, compared to previous heading: <H3>
+     * <h5> ... </h5>
+       ^
+AccessibilityTest.java:46: error: no "alt" attribute for image
      * <img src="x.jpg">
        ^
-AccessibilityTest.java:41: error: no summary or caption for table
+AccessibilityTest.java:61: error: no summary or caption for table
      * <table><tr><th>head<tr><td>data</table>
                                       ^
-4 errors
+8 errors
--- a/test/langtools/tools/doclint/html/BlockTagsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/doclint/html/BlockTagsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  * @library ..
  * @modules jdk.compiler/com.sun.tools.doclint
  * @build DocLintTester
- * @run main DocLintTester -Xmsgs BlockTagsTest.java
+ * @run main DocLintTester -Xmsgs:-accessibility BlockTagsTest.java
  */
 
 /** */
--- a/test/langtools/tools/doclint/html/HtmlVersionTagsAttrsTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/doclint/html/HtmlVersionTagsAttrsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -83,7 +83,7 @@
      * </ol>
      * <img src="testImg.jpg" alt="imgTest" crossorigin="anonymous">
      * <div aria-labelledby="Topics" aria-describedby="t1">
-     * <h1 id="Topics">Topics</h1>
+     * <h4 id="Topics">Topics</h4>
      * <p id="t1">Aria attribute test</p>
      * <p id="t2" aria-label="Label">Label test</p>
      * </div>
@@ -98,8 +98,8 @@
      * <p><tt>Teletype text</tt></p>
      * <section>
      * <hgroup>
-     * <h1>Section</h1>
-     * <h2> Another heading</h2>
+     * <h4>Section</h4>
+     * <h5> Another heading</h5>
      * </hgroup>
      * hgroup no longer supported in HTML5.
      * </section>
@@ -113,12 +113,12 @@
     /**
      * <section>
      * <p>Testing section tag</p>
-     * <h1>Section</h1>
+     * <h4>Section</h4>
      * Section text.
      * </section>
      * <article>
      * <p>Testing article tag</p>
-     * <h1>Article</h1>
+     * <h5>Article</h5>
      * Article text.
      * </article>
      * <header>
@@ -133,7 +133,7 @@
      * Main content
      * </main>
      * <aside>
-     * <h2>Test aside</h2>
+     * <h4>Test aside</h4>
      * <p>Description</p>
      * </aside>
      * <ul>
--- a/test/langtools/tools/doclint/tidy/AnchorAlreadyDefined.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/doclint/tidy/AnchorAlreadyDefined.java	Tue Mar 26 09:05:10 2019 -0400
@@ -13,6 +13,6 @@
 /**
  * <a name="here">valid</a>
  * <a name="here">duplicate</a>
- * <h1 id="here">duplicate</h1>
+ * <h2 id="here">duplicate</h2>
  */
 public class AnchorAlreadyDefined { }
--- a/test/langtools/tools/doclint/tidy/AnchorAlreadyDefined.out	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/doclint/tidy/AnchorAlreadyDefined.out	Tue Mar 26 09:05:10 2019 -0400
@@ -2,6 +2,6 @@
  * <a name="here">duplicate</a>
       ^
 AnchorAlreadyDefined.java:16: error: anchor already defined: "here"
- * <h1 id="here">duplicate</h1>
+ * <h2 id="here">duplicate</h2>
        ^
 2 errors
--- a/test/langtools/tools/doclint/tidy/MissingTag.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/doclint/tidy/MissingTag.java	Tue Mar 26 09:05:10 2019 -0400
@@ -13,6 +13,6 @@
 
 /**
  * </p>
- * <h1> <b> text </h1>
+ * <h2> <b> text </h2>
  */
 public class MissingTag { }
--- a/test/langtools/tools/doclint/tidy/MissingTag.out	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/doclint/tidy/MissingTag.out	Tue Mar 26 09:05:10 2019 -0400
@@ -2,6 +2,6 @@
  * </p>
    ^
 MissingTag.java:16: error: end tag missing: </b>
- * <h1> <b> text </h1>
+ * <h2> <b> text </h2>
         ^
 2 errors
--- a/test/langtools/tools/javac/doclint/ImplicitHeadersTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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 8006346
- * @summary doclint should make allowance for headers generated by standard doclet
- * @compile -Xdoclint:all/public ImplicitHeadersTest.java
- */
-
-/**
- * <h3> Header </h3>
- */
-public class ImplicitHeadersTest { }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/doclint/ImplicitHeadingsTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 8006346
+ * @summary doclint should make allowance for headings generated by standard doclet
+ * @compile -Xdoclint:all/public ImplicitHeadingsTest.java
+ */
+
+/**
+ * <h2> Class heading </h2>
+ */
+public class ImplicitHeadingsTest {
+    /**
+     * <h4>Method heading</h4>
+     */
+    public void m() { }
+}
+
--- a/test/langtools/tools/javac/file/SymLinkArchiveTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/javac/file/SymLinkArchiveTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -33,6 +33,7 @@
  * @run main SymLinkArchiveTest
  */
 
+import java.nio.file.FileSystemException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -69,7 +70,13 @@
         tb.writeFile(javaFile, "class T extends p.B {}");
 
         Path jar = base.resolve("lib.jar");
-        Files.createSymbolicLink(jar, classpath.getFileName());
+        try {
+            Files.createSymbolicLink(jar, classpath.getFileName());
+        } catch (FileSystemException fse) {
+            System.err.println("warning: test passes vacuously, sym-link could not be created");
+            System.err.println(fse.getMessage());
+            return;
+        }
 
         Result result = new JavacTask(tb).files(javaFile).classpath(jar).run(Expect.FAIL);
         String output = result.getOutput(OutputKind.DIRECT);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/file/SymLinkShortNameTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019, Google LLC. 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 8193277
+ * @summary SimpleFileObject inconsistency between getName and getShortName
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.classfile
+ * @build toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox
+ * @run main SymLinkShortNameTest
+ */
+
+import java.nio.file.FileSystemException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import toolbox.JavacTask;
+import toolbox.Task.Expect;
+import toolbox.Task.OutputKind;
+import toolbox.Task.Result;
+import toolbox.TestRunner;
+import toolbox.TestRunner.Test;
+import toolbox.ToolBox;
+
+public class SymLinkShortNameTest extends TestRunner {
+    public static void main(String... args) throws Exception {
+        new SymLinkShortNameTest().runTests(m -> new Object[] {Paths.get(m.getName())});
+    }
+
+    private final ToolBox tb = new ToolBox();
+
+    public SymLinkShortNameTest() {
+        super(System.err);
+    }
+
+    @Test
+    public void testJarSymlink(Path base) throws Exception {
+        Files.createDirectories(base);
+        Path b = base.resolve("B.java");
+        tb.writeFile(b, "class B { int f() {} }");
+
+        Path a = base.resolve("A.java");
+        try {
+            Files.createSymbolicLink(a, b.getFileName());
+        } catch (FileSystemException fse) {
+            System.err.println("warning: test passes vacuously, sym-link could not be created");
+            System.err.println(fse.getMessage());
+            return;
+        }
+
+        {
+            Result result =
+                    new JavacTask(tb).options("-XDrawDiagnostics").files(a).run(Expect.FAIL);
+            String output = result.getOutput(OutputKind.DIRECT);
+
+            String expected = "A.java:1:20: compiler.err.missing.ret.stmt";
+            if (!output.contains(expected)) {
+                throw new AssertionError(
+                        "expected output to contain: " + expected + "\nwas:\n" + output);
+            }
+        }
+        {
+            Result result = new JavacTask(tb).files(a).run(Expect.FAIL);
+            String output = result.getOutput(OutputKind.DIRECT);
+
+            String expected = "A.java:1: error: missing return statement";
+            if (!output.contains(expected)) {
+                throw new AssertionError(
+                        "expected output to contain: " + expected + "\nwas:\n" + output);
+            }
+        }
+    }
+}
--- a/test/langtools/tools/javac/modules/MOptionTest.java	Tue Mar 26 08:57:28 2019 -0400
+++ b/test/langtools/tools/javac/modules/MOptionTest.java	Tue Mar 26 09:05:10 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8146946 8176743
+ * @bug 8146946 8176743 8200286
  * @summary implement javac -m option
  * @library /tools/lib
  * @modules
@@ -39,7 +39,6 @@
 
 import toolbox.JavacTask;
 import toolbox.Task;
-import toolbox.ToolBox;
 
 public class MOptionTest extends ModuleTestBase {
     public static void main(String... args) throws Exception {
@@ -93,9 +92,10 @@
             throw new AssertionError("Classfile update!");
         }
 
-        Thread.sleep(2000); //timestamps
-
-        Files.setLastModifiedTime(testTest, FileTime.fromMillis(System.currentTimeMillis()));
+        // Date back the source file by one second compared to the current time.
+        // Cases have been observed where the resulting class file had an earlier
+        // timestamp than the java source.
+        Files.setLastModifiedTime(testTest, FileTime.fromMillis(System.currentTimeMillis() - 1000));
 
         new JavacTask(tb)
                 .options("-m", "m1x", "--module-source-path", src.toString(), "-d", build.toString())
@@ -235,10 +235,11 @@
             throw new AssertionError("Classfile update!");
         }
 
-        Thread.sleep(2000); //timestamps
-
-        Files.setLastModifiedTime(C1Source, FileTime.fromMillis(System.currentTimeMillis()));
-        Files.setLastModifiedTime(C2Source, FileTime.fromMillis(System.currentTimeMillis()));
+        // Date back the source file by one second compared to the current time.
+        // Cases have been observed where the resulting class file had an earlier
+        // timestamp than the java source.
+        Files.setLastModifiedTime(C1Source, FileTime.fromMillis(System.currentTimeMillis() - 1000));
+        Files.setLastModifiedTime(C2Source, FileTime.fromMillis(System.currentTimeMillis() - 1000));
 
         new JavacTask(tb)
                 .options("-m", "m1x,m2x", "--module-source-path", src.toString(), "-d", build.toString())